Хочу поделиться опытом разработки приложения с просмотром видео контента для SmartTV (Tizen и WebOS) и с какими проблемами мы столкнулись.

На современных телевизорах, как мы знаем, можно устанавливать разные приложения, для облегчения работы с какими-то ресурсами и контентом. В большинстве случаев, эти приложения под капотом это обычный браузер, на теликах это Chromium.

Так как это браузер, то ничего нам не мешало использовать React.js для разработки, что повлияло на некоторые проблемы с производительностью.

Я не буду рассказывать о том, как именно нужно делать с примерами кода, я расскажу о нюансах и решениях, которые были приняты.

Пройдемся по основным моментам:

  1. Ограниченные ресурсы
  2. Навигация
  3. Производительность стилей и рендеринга
  4. Видео плееры
  5. Backend

Ограниченные ресурсы


На телевизоре не так много памяти и производительности, как на наших компьютерах, поэтому первая проблема это ограничение ресурсов.

Например для приложения выделяется всего около 250 мегабайт на использование и мы столкнулись с такой проблемой, что при отображении грида с контентом (картинка, описание, рейтинг) могла расходоваться память на пределе, когда в гриде всего 1000 элементов и мы скроллим вниз, то размер картинок увеличивается и увеличивается и в какой-то момент приложение крэшится с надписью, что закончилась память.

Решение этой проблемы react-window
Он не хранит все элементы вне окна в DOM.

Навигация


Если на компьютере мы привыкли, что мы кликаем мышкой по элементам на сайте, то на телевизорах мы пользуемся пультом, который бывает и с возможностью использования как мышь, но в большинстве это кнопки. Отсюда вылазит проблема навигации, что мы должны обрабатывать нажатия кнопок пульта и навигировать по всему приложению без курсора, но, в то же время нам необходимо и обрабатывать нажатия на элементы с помощью «клика».
Некоторые коды кнопок на пультах LG и Samsung отличаются, как и отличаются от клавиатуры обычной, поэтому для каждой платформы у нас были захардкожены коды кнопок, которые мы обрабатываем.

Пример Tizen
Tizen

export default {
  KEY_0: 48,
  KEY_1: 49,
  KEY_2: 50,
  KEY_3: 51,
  KEY_4: 52,
  KEY_5: 53,
  KEY_6: 54,
  KEY_7: 55,
  KEY_8: 56,
  KEY_9: 57,
  KEY_UP: 38,
  KEY_DOWN: 40,
  KEY_LEFT: 37,
  KEY_RIGHT: 39,
  KEY_OK: 13,
  KEY_BACK: 10009,
  KEY_CHANNEL_UP: 427,
  KEY_CHANNEL_DOWN: 428,
  KEY_MEDIA_FAST_FORWARD: 417,
  KEY_MEDIA_PAUSE: 19,
  KEY_MEDIA_PLAY: 415,
  KEY_MEDIA_PLAY_PAUSE: 10252,
  KEY_MEDIA_REWIND: 412,
  KEY_MEDIA_STOP: 413,
  KEY_DEBUG_TOGGLE_CONSOLE: 403,
  KEY_DEBUG_TOGGLE_QUICK_EDIT: 404,
  KEY_DEBUG_SET_FAVOURITES: 405,
  KEY_DEBUG_CLEAR_FAVOURITES: 406,
  KEY_SHOW_REMOTE_POINTER: 7777777, // not applicable
  KEY_HIDE_REMOTE_POINTER: 7777777, // not applicable
};

WebOS

export default {
  KEY_0: 48,
  KEY_1: 49,
  KEY_2: 50,
  KEY_3: 51,
  KEY_4: 52,
  KEY_5: 53,
  KEY_6: 54,
  KEY_7: 55,
  KEY_8: 56,
  KEY_9: 57,
  KEY_UP: 38,
  KEY_DOWN: 40,
  KEY_LEFT: 37,
  KEY_RIGHT: 39,
  KEY_OK: 13,
  KEY_BACK: 461,
  KEY_MEDIA_FAST_FORWARD: 417,
  KEY_MEDIA_PAUSE: 19,
  KEY_MEDIA_PLAY: 415,
  KEY_MEDIA_PLAY_PAUSE: 10252,
  KEY_MEDIA_REWIND: 412,
  KEY_MEDIA_STOP: 413,
  KEY_CHANNEL_UP: 33,
  KEY_CHANNEL_DOWN: 34,
  KEY_DEBUG_SET_EMAIL: 403,
  KEY_DEBUG_TOGGLE_CONSOLE: 404,
  KEY_DEBUG_TOGGLE_QUICK_EDIT: 405,
  KEY_DEBUG_SET_FAVOURITES: 406,
  KEY_DEBUG_CLEAR_FAVOURITES: 407,
  KEY_SHOW_REMOTE_POINTER: 1536,
  KEY_HIDE_REMOTE_POINTER: 1537,
};

Клавиатура

export default {
  KEY_0: 48,
  KEY_1: 49,
  KEY_2: 50,
  KEY_3: 51,
  KEY_4: 52,
  KEY_5: 53,
  KEY_6: 54,
  KEY_7: 55,
  KEY_8: 56,
  KEY_9: 57,
  KEY_UP: 38,
  KEY_DOWN: 40,
  KEY_LEFT: 37,
  KEY_RIGHT: 39,
  KEY_OK: 13,
  KEY_BACK: 8, // backspace
  KEY_MEDIA_FAST_FORWARD: 70, // f
  KEY_MEDIA_PLAY_PAUSE: 80, // p
  KEY_MEDIA_REWIND: 66, // b
  KEY_MEDIA_STOP: 83, // s
  KEY_CHANNEL_UP: 70, // f
  KEY_CHANNEL_DOWN: 71, // g
  KEY_DEBUG_SET_EMAIL: 81, // q
  KEY_DEBUG_TOGGLE_CONSOLE: 87, // w
  KEY_DEBUG_TOGGLE_QUICK_EDIT: 69, // e
  KEY_DEBUG_SET_FAVOURITES: 88, // w
  KEY_DEBUG_CLEAR_FAVOURITES: 82, // r
  KEY_SHOW_REMOTE_POINTER: 7777777, // not applicable
  KEY_HIDE_REMOTE_POINTER: 7777777, // not applicable
};

Как можно заметить, на клавиатуре это кнопки с буквами (в комментариях указаны).

Для того, чтоб обрабатывать навигацию через нажатие кнопок и нажатие мышью, у нас результатом был всегда один event — mouseClick, тем самым мы одинаково обрабатывали все события.

Другой особенностью навигации является фокус, на каждом экране должен быть элемент в фокусе, потому что потеряв фокус, мы уже не сможем навигировать по экрану. Каждому элементу прописывались свойства focus и id фокуса. При навигации нужно было всегда это учитывать, но и к тому же, иногда возникает требование при возвращении назад восстанавливать состояние полностью предыдущего экрана, поэтому навигация была написана полностью кастомная.

Производительность стилей и рендера


Анимация на CSS работает медленно на телевизорах, особенно, когда DOM элементов, которые попадают в анимирование много, можно увидеть не плавное изменение а слайд-шоу. Один из вариантов решение этой проблемы — canvas. Отрисовка на нем, анимация, подсветка при навигировании ускоряют работу в разы, но, если у вас есть автоматизаторы, то им такая реализация может не понравиться, т.к им сложно по картинке проверять контент.

Много перерендереваний на странице — еще одна боль, все начинает тормозить, дергаться. Нужно было максимально контролировать этот процесс, после чего shouldComponentUpdate компонентов выглядит так:

image

В итоге переписали чувствительные части приложения на vanilla js, стало быстрее.

Видео плееры


У LG и Samsung разные видео плееры, что тоже создает дополнительные трудности при разработке. Для LG используется video-тег, для Samsung AVPlay sdk. Поэтому есть отличия в функциональности, нужно учитывать, что не все возможности одинаковы и могут отличаться от версии к версии ОС.

Также  были проблемы с нагрузкой при запуске видео — решалось кэшированием, параллелизацией и откладыванием запросов, обработок.

Backend


На скорость работы влияет качество бэкенда, скорость обработки запросов и их количество. На стороне FE должно быть минимальное количество обработки данных. Если нужно подгружать большие объемы даных, можно использовать web workers.

Комментарии (19)


  1. some_x
    19.09.2019 09:21

    После прочтения статьи появляется вопрос, почему для телевизоров пишут на web-технологиях, если там так мало ресурсов? Больше подошло бы что-то вроде Qt.


    1. JustDont
      19.09.2019 09:58

      После прочтения статьи появляется вопрос, почему для телевизоров пишут на web-технологиях

      Скорее уж появляется вопрос — почему на медленных и ресурсоёмких веб-технологиях? Реакт с его виртуальным DOM, серьезно? А между реактом и vanilla.js прям вообще ничего нет?


      1. yantishko Автор
        19.09.2019 10:30

        Тут приводится проблемы конкретно для React.js, это естественно не единственный способ реализации приложения для телевизоров :) А что между реактом и ванилой вы предлагаете?


        1. leotada
          19.09.2019 11:18
          +1

          А что между реактом и ванилой вы предлагаете?

          svelte.dev

          mustlab.ru/ru судя по докладам и статьям PaulMaly уже несколько лет успешно используют svelte для разработки под ТВ.


          1. yantishko Автор
            19.09.2019 11:18

            спасибо, почитаю


        1. JustDont
          19.09.2019 13:25

          А что между реактом и ванилой вы предлагаете?

          Всё, что левее реакта. Там конечно далеко не всё предлагает высокую степень абстрагирования от деталей, но там много и высокоуровневых фреймворков. Да тот же даже preact намного быстрее и тоньше. И про svelte уже сказали — тут как раз отличный кейс для неё, да.


    1. yantishko Автор
      19.09.2019 10:29

      Tizen позволяет писать на .net, WebOS не вижу такой поддержки. Основная идея была — переиспользование кода между разными ОС теликов и использование общей sdk для web части


  1. harry2019
    19.09.2019 11:21

    В большинстве случаев, эти приложения под капотом это обычный браузер, на теликах это Chromium

    Что понимается под «большинством случаев»? Например, на моем LG 32" (Smart) стоит именно Chrome, причем ну очень старенький, 28-ая версия.


    1. yantishko Автор
      19.09.2019 11:31

      В спецификации либо WebKit, либо Chromium.
      webostv.developer.lge.com/discover/specifications/web-engine

      В статье имелось ввиду, что приложение может быть написано на .net, и это уже будет не браузер


  1. leotada
    19.09.2019 11:30

    Если позволите, еще дополню ссылками. В jsunderhood была неделя разработчика под смарт тв. Архива нет, но вот несколько веток с интересными особенностями такой разработки:

    twitter.com/jsunderhood/status/1172215584303570945
    про выкладывание в сторы

    twitter.com/jsunderhood/status/1172224195536838656
    про написание приложений под тв

    twitter.com/jsunderhood/status/1172194802076663808
    на что похожа разработка под смарт тв


  1. pahonski
    19.09.2019 12:17

    Подскажите, а какой плеер вы использовали для webOs, какой там SDK?


    1. yantishko Автор
      19.09.2019 12:33

      Для WebOS использовался HTML5 тег video и работа велась с ним.
      Для взаимодействия с WebOS использовалась Web API webostv.developer.lge.com/api/webostvjs/webos

      Для Tizen использовался AVPlay developer.samsung.com/tv/develop/guides/multimedia/media-playback/using-avplay


      1. vitalets
        19.09.2019 15:18

        Тогда все-таки в статье не совсем корректно указано, что и у LG и у Samsung разные нативные видео плееры с разным sdk. Насколько я знаю, у LG нет аналога самсунговского AVPlay и все играется только через video-тег.


        1. yantishko Автор
          20.09.2019 11:44

          Спасибо, исправил


  1. wrqqq
    19.09.2019 12:57

    Маловато. Не очень понимаю в чем цель статьи?
    Вы перечислили несколько проблем, ок. Но никаких выводов, никаких интересных поворотов.
    Тоже что ли пойти написать статью как я вчера вебпак настраивал.


  1. vitalets
    19.09.2019 15:22

    Дополню еще ссылкой на подборку awesome-smart-tv, где собраны полезные библиотеки и фреймворки для смартов.


    Кстати, в контексте статьи было бы интересно узнать, пробовали ли вы react-tv? Кажется там некоторые тв-специфичные проблемы должны быть решены.


    1. yantishko Автор
      20.09.2019 11:41

      Спасибо за ссылку.
      На практике не пробовали react-tv, но есть и + и -, поддержка только webOS, ну и использование не проверенной библиотеки на enterprise проектах чревато. Когда разработка стартовала, на тот момент react-tv только появился и был сыроват.
      А так да, он решает многие проблемы, может у кого был практический опыт использования react-tv?


  1. i360u
    19.09.2019 16:17

    Для меня главным ограничением в Tizen стала древняя версия Chromium, которая имеет проблемы с поддержкой многих вещей, к которым мы давно привыкли в современных браузерах. У Samsung все ОЧЕНЬ ПЛОХО с обновлениями SmartTV: большинство продающихся на рынке телевизоров работают на версии Tizen, которую не поддерживает их-же собственный SDK. И обновить их нельзя. Ну и React там, конечено, совсем не нужен.


  1. technic93
    19.09.2019 20:14

    Приставочку на андроид прикупить дешевле. Хотя на моем Самсунге Ютуб и нетфликс более менее работают из коробки.