image

Привет, Хабр!

Уже давно была идея написать статью о проблемах SmartTV разработки, но по ходу погружения в эту область, мы изобрели свой велосипед, который помогал нам эти проблемы решать. Поэтому, в данной статье, мы не только осветим некоторые проблемные моменты SmartTV разработки, но и расскажем о том как их решить с помощью очередного нового фреймворка PureQML.

Всем кому интересна данная тема или просто любопытно посмотреть на новый фреймворк, который может и в SmartTV, просим под кат.

Зоопарк


Начнем с того, что в природе существует множество SmartTV платформ и многие из них заточены для запуска web приложений. Отсюда может появиться иллюзия, что достаточно один раз написать код и использовать его на всех платформах. Но на деле все платформы имеют некоторые отличия, которые приходится учитывать. Среди таких особенностей можно выделить следующие:

  • Обработка нажатий кнопок дистанционного пульта. Не все производители используют одинаковые кейкоды для одних и тех же кнопок пульта. В качестве примера, можно сравнить кей коды для платформы orsay и webos. Для tizen же надо явно регистрировать некоторые кнопки для дальнейшего использования.
  • Видеоплеер. Во многих платформах поддерживается html5 video плеер, но, к примеру, для tizen используется AVPlay, а для orsay используется собственное API для работы с нативным плеером.
  • Информация о девайсе. Получение информации об устройстве в каждой платформе также реализовано по разному, в NetCast создается специальный объект со особым id-шником, в других случаях используются специфические для каждой платформы методы.
  • Фокус. SmartTV приложение в первую очередь ориентировано на управление пультом, а следовательно UI/UX должны быть реализованы с учетом использования навигационных кнопок: вверх, вниз, вправо, влево, ОК и назад, при этом важно не терять фокус и явно обозначать, где он сейчас находится.

Документация


Помимо разнообразия платформ и документации к этим платформам, проблема заключается в том, что некоторые производители выпускают новые версии, которые, порой, теряют совместимость в некоторых местах, а то и вовсе переходят на новые платформы, в принципе несовместимые с прежними (как например, переход LG с NetCast на WebOS). При этом идет интенсивное продвижение новых платформ, из-за чего информацию по старым платформам найти становится непросто, так как некоторые разделы документации удаляются или переносятся, из-за чего иногда можно наткнуться на мертвые ссылки в советах на формах.

Установка


Опять же из-за многообразия платформ, процесс установки приложений на сами устройства для отладки также отличается. К примеру, для AndroidTV можно воспользоваться adb, на tizen есть свой аналог — sdb, для WebOS специальные CLI скрипты и т.д. Каждый из этих инструментов нужно устанавливать и настраивать. Сюда же можно добавить проблему интенсивного обновления платформ, с сопутствующим обновлением SDK и IDE. В качестве примера такой проблемы можно привести случай с Tizen Studio. Скачав самую последнюю версию, вы сможете устанавливать приложения только на телевизоры TV-samsung tv4, при этом нет простого способа установить приложение на более ранние версии телевизоров, коих в природе сейчас значительно больше (если вдруг столкнулись с этой проблемой см. ссылку) и даже после успешного танца с бубном, IDE теряет возможность устанавливать приложения на телевизоры TV-samsung tv4 ?\_(?)_/?

Модерация


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

Также надо быть готовым к тому, что причиной отказа может оказаться любая мелочь, например, ошибочный ответ в self чеклисте (список вопросов, на которые должен ответить разработчик перед отправкой приложения, например: “содержит ли Ваше приложение вирусы” и т.п.) или из-за недопонимания в описании UX приложения. Может дойти и до курьезных ситуаций, например, был случай, когда завернули приложение со стримингом телеканалов, из-за того, что приняли бегущую строку в эфире одного из каналов за артефакт графики, приняв ее за часть OSD.

AndroidTV & tvOS


Отдельно стоит отметить AndroidTV и tvOS, т.к. эти платформы не поддерживают явный запуск web приложений. Для tvOS используется собственный xml-подобный язык: TVML, и что особенно интересно, на этом языке можно верстать, но только в рамках определенного набора шаблонов, сделать что-то совсем произвольное довольно непросто. С помощью таких ограничений все приложения для tvOS вынуждено придерживаются единого style-гайда и если от него далеко не отходить, то процесс написания приложения будет прост.

На андройде ситуация получше, т.к. есть способы запускать web приложения, про один из них расскажем чуть ниже.

Как мы делаем это


Столкнувшись с реальностью, сперва изучили существующие решения, но к сожалению ничего универсального и удобного не приглянулось: смартбокс неудобный, реакт не решает специфических тв проблем, как, собственно, и другие фреймворки, которые больше ориентированы на web.

Теперь рассмотрим, как с этим справляется PureQML (про который мы уже как-то писали тут и тут). Вкратце это js-фреймворк, который позволяет декларативно описывать UI на qml-like языке, что помогает быстро создавать приложения абстрагируясь от html, css и прочего. Для решения конкретно SmartTV проблем был написан отдельный модуль qmlcore-tv под лицензией CC-BY-4.0, который поддерживает следующие платформы:

  • LG WebOS
  • LG NetCast
  • Samsung Tizen
  • Samsung Orsay
  • Opera TV
  • Hisense
  • AndroidTV

И вот как он решает вышеперечисленные проблемы:

  • Обработка кнопок пульта. Для поддерживаемых платформ реализован маппинг кейкодов и в клиентском коде достаточно просто написать нужный обработчик, например, для красной функциональной кнопки пульта можно написать обработчик:
    onRedPressed { /* код обработчика */ }
  • Видеоплеер. Для работы с плеером есть специальная компонента VideoPlayer, которая описывает интерфейс для работы с видео, а платформенная реализация выбирается для целевой платформы на этапе сборки. Ниже приведен пример использования: проигрывание зацикленного видео по ссылке на весь экран:

    
    	VideoPlayer {
    		width: 100%;
    		height: 100%;
    		autoPlay: true;
    		source: "http://media.w3.org/2010/05/bunny/movie.mp4";
    	}
    
  • Информация о девайсе. Для того чтобы получить сведения об устройстве достаточно использовать контрол Device, по аналогии с плеером он описывает интерфейс, а реализация берется для собираемой платформы. Ниже приведен пример кода для отображения текста с ID устройства на экране:

    
    	Device { id: device; }
    
    	Text {
    		text: “DeviceID: ” + device.deviceId;
    	}
    
  • Фокус. Тут уже помогает базовая особенность самого фреймворка, то что в один момент времени существует только один единственный фокус, который есть и никуда не исчезает. Для работы с фокусом можно использовать декларативные свойства:
    focus — булевый флаг, указывающий, что данный элемент фокусабелен или нет
    activeFocus — булевый флаг, который принимает значение true, когда данный элемент содержит фокус, и false в противном случае
  • Установка. Для удобной установки PureQML приложений на ТВ можно воспользоваться скриптом smart-tv-deployer, достаточно склонить его в корень PureQML проекта. Чтобы собрать проект, скажем, для webos телевизора с именем “myTV” (только перед этим необходимо настроить ТВ, подробнее про настройку WebOS телевизора смотри тут), нужно вызвать команду:

    ./smart-tv-deployer/build -p webos -t myTV
  • AndroidTV. Тут как и для андройда, нативный язык — java, и для того, чтобы портировать web приложение туда мы воспользовались проектом cordova. Этот фреймворк позволяет сгенерировать android приложение с WebView, в котором запускается уже само web приложение. Также, сейчас ведутся активные работы по трансляции PureQML кода в натив.

Пример


В качестве примера, покажем как портировать приложение из прошлой статьи на SmartTV.

Как мы уже упоминали выше, UX на ТВ отличается от десктопного браузера и в код придется добавить некоторые правки для поддержки работы с кнопками пульта:


	onSelectPressed: { osd.toggleActive() }

	onBackPressed: {
		if (osd.active)
			osd.toggleActive()
		else
			_globals.closeApp()
	}

В данном коде добавили обработку нажатия кнопок «Select» и «Back», при нажатии первой включаем/выключаем OSD (тот, что с картой и точкой местоположения станции) при нажатии «Back», если открыт OSD закрываем его, если он закрыт, то закрываем само приложение.
Конечный результат можно увидеть на видео:


Заключение


В итоге PureQML неплохо показал себя в качестве инструмента для разработки SmartTV приложений, мы и сами интенсивно пользуемся им для этих целей.
Если у вас появились вопросы или хотите больше статей про SmartTV разработку или PureQML — пишите в комментариях или на телеграм канал, постараемся на все ответить.

Спасибо за внимание! =)

Ссылки


Сайт проекта
Страница на github
Исходники earth-online
Телеграмм канал поддержки

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


  1. UksusoFF
    27.08.2018 21:44

    А где-нибудь есть список приложений разработанных на этом фреймворке? Было бы интересно что-то кроме плееров вообще делают?
    У меня телевизор Samsung 2012 года, это я так понимаю Orsay. Ничего нового на них уже никто не пилит. Разве что XSMART из недавнего довольно качественно сделан.


    1. PaulMaly
      27.08.2018 21:58

      Более того, на них ничего нового уже и не запилить)))


      1. UksusoFF
        27.08.2018 22:04

        Ну кроме очевидного ответа "Это никому не нужно", то почему?


        1. PaulMaly
          27.08.2018 22:05
          +1

          Потому что регистрацию приложений там закрыли ещё года 3 назад))


          1. UksusoFF
            27.08.2018 22:10

            Ну через официальные источники — ок. Но можно поставить ручками.
            А раз фреймворк из статьи позволяет писать под эту платформу значит кто-то для чего-то ее использует?


            1. PaulMaly
              27.08.2018 22:17
              +1

              Легаси проекты в основном. Новые проекты делаем только на WebOS и Tizen.


    1. comrat Автор
      27.08.2018 23:14
      +1

      Если вендор заинтересован в приложении, то 12 год открывают, иногда даже 11. На pure есть коммерческие приложения под все эти платформы в проде, с немалым числом абонентов, но мне разрешения не давали, а бумагу что буду помалкивать я подписал, поэтому от конкретных референсов воздержусь, но прод большой и коммерческий.


      1. UksusoFF
        27.08.2018 23:18

        Понятно, я было подумал что опенсорс и все такое :)


  1. inoyakaigor
    27.08.2018 23:10

    Эх, где вы были в 2015 с этой статьёй?!


  1. juDge
    28.08.2018 01:25

    На текущий момент имею приложение под webOS и есть в плане выход на другие платформы. Но скорее всего подобную платформу для унификации использовать все равно не буду. По мне это еще один костыль. На той же webOS 1.х есть например проблема с производительностью интерфейсов на HTML5… что то красивое и анимированное не реально… интерфейс начинает банально тупить. Отрисовка происходит ооочень медленно.


    1. comrat Автор
      28.08.2018 01:48

      Да, сталкивались с такой проблемой. Где не помогали оптимизации, выключали анимации для таких платформ. В манифесте для этого сделали специальный флаг, который выключает анимации все глобально: disableAnimations.
      И этот флаг можно задать не только в манифесте, но и в рантайме. Вот примерный код, как вырубить анимации только для webos 1й версии:

      Device { id: device; }
      
      onCompleted: {
      	var platform = this._context.system.os.toLowerCase();
      	var sdk = device.sdk;
      	$manifest$disableAnimations = (platform === "webos" && sdk.indexOf("1.") === 0);
      }
      


  1. Acionyx
    28.08.2018 10:19

    Интересное решение, коллега. А чем вас не устроил реакт или любая другая библиотека для управления отображением?
    Мы с успехом применяем jsx, но не при помощи реакта, правда.


    1. comrat Автор
      28.08.2018 10:20

      Хотя бы из-за того, что не надо руками за фокусом следить и описывать все переходы при навигации


      1. Acionyx
        28.08.2018 10:23

        А как здесь реализуется сложная логика переходов фокуса без её явного описания? Например, для элементов разных списков нужны разные действия при нажатии одних и тех же кнопок.


        1. comrat Автор
          28.08.2018 10:56

          Ну несколько примеров разных кейсов могу првести:
          1) Навигация во вьюхах уже реализована по умолчанию. Для того, чтобы работала там навигация на любом ТВ в принципе не нужно писать ничего
          2) Навигация среди разнородных элементов. Если элементы разные но расположены скажем в горизонтали или вертикали, или просто подряд гридом, то для этого есть специальные лейауты:
          Row, Column и Grid соответственно, и чтобы орагнизовать среди них навигацию, достаточно указать у этих элементов флаг «focus: true;», чтобы показать что элементы фокусабельны. Пример:

          Row {
          	height: 100;
          	spacing: 10;
          
          	Rectangle {
          		height: 100;
          		width: 200;
          		color: activeFocus ? "red" : "blue";
          		focus: true;
          	}
          
          	Image {
          		height: 100;
          		width: 100;
          		source: activeFocus ? "res/focusedImage.png" : "res/image.png";
          		focus: true;
          	}
          }
          

          логика навигации здесь также уже реализована, и ничего дополнительно писать зесь не нужно.
          3) Явно передать фокус при нажатии какой-то кнопки. Например, нужно передать фокус другому элементу при нажатии вверх и вернуть его обратно, нажав вниз:
          Rectangle {
          	id: topRect;
          	width: 100;
          	height: 100;
          	color: "red";
          	focus: true;
          
          	onDownPressed: { bottomRect.setFocus(); }
          }
          
          Rectangle {
          	id: bottomRect;
          	y: 100;
          	width: 100;
          	height: 100;
          	color: "blue";
          	focus: true;
          
          	onUpPressed: { topRect.setFocus(); }
          }
          

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


          1. juDge
            28.08.2018 12:28

            У себя я реализовал поиск ближайшего элемента в зависимости от необходимого элемента. Т.е. если нажимаем клавишу «вправо»… то ищутся ближайжие элементы с права от элемента… можно искать как относительно оси так и в приницпе все что справа… или например найти по осои и если ни чего не нашлось то ищим уже в более широком смысле… т.е. все что справа… не то чтобы универсально… в некоторых случаях требуется подстройка алгоритма в виду более сложного строения элементов UI. Но в общем и целом справляется… при этом круг поиска может сужаться если например открыто диалоговое окно.


            1. juDge
              28.08.2018 13:06

              >необходимого элемента
              необходимого направления =)


            1. PaulMaly
              28.08.2018 20:15

              В своё время была большим открытием либа: www.npmjs.com/package/spatial-navigation-js

              Даже без особого конфигурирования работает очень не плохо, но можно довольно гибко подстроить.


              1. juDge
                28.08.2018 21:52

                Интересно… глыну по подробней. У меня по сути так же работает… на дистанциях. spatial завязана на JQuery… у меня сейчас тоже в одном месте используется JQuery но надо убирать этот костыль… переписываю на чистый js.
                Опять же как я понял spatial берет полный контроль за нажатиями на себя, мне данный вариант не совсем подходит потому как у меня навигация чуть сложнее… есть скрытые элементы которые должны отобразиться при определенных обстоятельствах и получить фокус.


                1. PaulMaly
                  28.08.2018 22:18

                  Интересно… глыну по подробней. У меня по сути так же работает… на дистанциях. spatial завязана на JQuery… у меня сейчас тоже в одном месте используется JQuery но надо убирать этот костыль… переписываю на чистый js.

                  Не, ну что вы ей Богу, какой jquery.))) Прямой завязки на него там конечно же нет. Просто если jquery подключен, через него делаются некоторые DOM операции и обертывается либа в плагин. Если его нет, и черт с ним))) Так что можете считать, что это чистый JS.

                  Опять же как я понял spatial берет полный контроль за нажатиями на себя, мне данный вариант не совсем подходит потому как у меня навигация чуть сложнее… есть скрытые элементы которые должны отобразиться при определенных обстоятельствах и получить фокус.

                  Там есть целый набор событий, которые можно использовать в качестве хуков. Далее, есть реально типа хука navigableFilter. Ну и главное там есть разделение на секции, и всякие там add/remove, enable/disable, pause/resume для управления этими секциями.

                  Например, вам нужно «замкнуть» фокус на модальном окне. Очень просто. Просто добавляем секцию для него с простым конфигом и при активации модалки, отдаем ей фокус:

                  // добавили секцию с restrict: 'self-only'
                  SN.add({
                    id: 'modal',
                    restrict: 'self-only'
                  });
                  
                  // когда надо отдаем ей фокус
                  SN.focus('modal');
                  


  1. nik210
    28.08.2018 10:21

    Смарт тв уже не так актуален, ведь есть хорошие приставки для телевизора с андроидом и большим функционалом на борту.
    Сам пытался сделать «Hello, Word» для телевизора самсунг в 2012 году


    1. comrat Автор
      28.08.2018 10:28

      Ну рынок этот пока все еще велик, причем до сих пор в полях есть немало телевизоров уже не поддерживаемых платформ, плюс покупать дополнительную приставку с еще одним пультом и hdmi проводом, чтобы, например, смотреть YouTube избыточно, когда на самом телевизоре это можно сделать с помощью встроенного SmartTV.
      Ну и добавлю, что на PureQML на AndroidTV тоже можено писать приложения =)


      1. miksoft
        28.08.2018 21:33

        чтобы, например, смотреть YouTube избыточно, когда на самом телевизоре это можно сделать с помощью встроенного SmartTV
        Увы, YouTube перестает работать в некоторых SmartTV. В Самсунге 12 или 13 года выпуска приложение YouTube сначала выдавало уведомление, что поддержка YouTube скоро будет удалена, а потом самоудалилось с телевизора. И поставить заново штатным путем нельзя, в маркете его просто нет.


    1. PaulMaly
      28.08.2018 10:30

      На самом деле очень даже актуален. Приставку нужно покупать отдельно, а смарт тв сейчас встроено во все телики. Большая часть людей, которая их покупает далеко не гики.


      1. Popadanec
        28.08.2018 14:06

        Далеко не во все. Я год полтора назад покупал тв 43". И моделей без него хватало. Искал именно без смарт тв. Т.к. разница с аналогичной моделью, но с ним на борту в районе 4-5тыр. И на эти деньги можно купить отличный андроид тв. Но его я правда так и не взял, т.к. появилось дома интерактивное тв приставка от ростелекома. А ютуб там особо ни кому не нужен.


    1. Immortal_pony
      28.08.2018 19:44

      Smart TV — это следующий шаг после приставки.


  1. PaulMaly
    28.08.2018 10:31

    > смартбокс неудобный, реакт не решает специфических тв проблем

    Как насчёт TAL?


    1. comrat Автор
      28.08.2018 10:57

      А можно ссылку?


    1. comrat Автор
      28.08.2018 11:06

      Вот этот TAL?


      1. PaulMaly
        28.08.2018 17:24

        Да, от BBC


    1. comrat Автор
      29.08.2018 16:25

      Посмотрел проект, но нам больше декларативный подход PureQML в описании UI нравится, т.к. позволяет более лаконично и явно описать то, что хочешь отобразить на экране, в качестве примера, продемонстрирую примерный код первой страницы talexample, если бы она была написана на PureQML:

      Image {
      	amchors.fill: context;
      	source: "res/main_bg.png";
      
      	Column {
      		width: 100%;
      		spacing: 10;
      		focus: true;
      
      		Text {
      			width: 100%;
      			text: "Hello World";
      			font.pixelSize: 72;
      			color: "#fff";
      			horizontalAlignment: Text.AlignHCenter;
      		}
      
      		Text {
      			width: 100%;
      			text: "Welcome to your first TAL application!";
      			font.pixelSize: 28;
      			color: "#fff";
      			horizontalAlignment: Text.AlignHCenter;
      		}
      
      		ListView {
      			width: 50%;
      			height: contentHeight;
      			spacing: 10;
      			focus: true;
      			model: ListModel {
      				ListElement { text: "Carousel Example"; }
      				ListElement { text: "Sample Video Player Example"; }
      				ListElement { text: "Horizontal Progress Bar Example"; }
      			}
      			delegate: Rectangle {
      				width: 100%;
      				height: 40;
      				color: activeFocus ? "#0ff" : "#ccc";
      
      				Text {
      					width: 100%;
      					height: 100%;
      					text: "Welcome to your first TAL application!";
      					font.pixelSize: 21;
      					color: "#000";
      					verticalAlignment: Text.AlignVCenter;
      					horizontalAlignment: Text.AlignHCenter;
      				}
      			}
      		}
      	}
      }
      


      1. PaulMaly
        29.08.2018 18:17

        Вам то понятно))) с другой стороны там BBC. Мы то вообще Svelte юзаем в последнее время.


  1. juDge
    28.08.2018 22:05

    Размышления на тему…
    Боюсь что данный данный проект (и вообще другие схожые) без серьезной поддержки производителя, возможности писать плагины и… достаточно длинного списка контрибутеров канет в Лету. Либо его поддерживать как побочный продукт используя в своем каком то проекте.
    Каждый проект как правило индивидуален… и зачастую ни один фреймворк не покрывает потребности. Либо не хватает функционала, либо не достаточну «кунфигурабелен»… либо слишком результат оказывается громоздким. Большой проект скорее всего будет использовать самописный «костыль» дабы получить максимум скорости работы интерфейса… как ни прискорбно но процессоры достаточно слабы в Смарт ТВ по сравнению с компами где можно городить не заботясь о том сколько будет весить проект… сколько пожрет процессорного времени и тд. Когда делал первые шаги на webOS 1.х не так редки были случаи когда программа просто вылетала… скорее всего из-за нехватки памяти.
    Было дело как-то если не ошибаюсь предлагали мне вроде поляки какой то фреймворк для создания мультиплатформенных приложения… но чет уже года полтороа или два я о данном фрейме даже не слышу… ну тут либо мало влезаю в данную тематику дальше своего проекта либо он так же канул в Лету.
    Несколько сумбурно но надеюсь суть ясна… что будет тяжело поддерживать подобный проект на плаву… если только много интузиазма либо как побочный продукт используемый в своих проектах.


    1. PaulMaly
      28.08.2018 23:03

      Поэтому мы уже больше года используем SvelteJS для Smart TV приложений и довольны как слоны))) Особенно после выхода второй версии.


  1. flamefork
    29.08.2018 10:48

    Писал под OperaTV (движок Presto, как в Opera 12) и NetCast времен 2013 года.
    webOS 1.х в плане производительности казался несбыточной мечтой…