Дорабатываем Яндекс.Станцию для просмотра YouTube

в 14:51, , рубрики: Кинопоиск, Программирование, реверс-инжиниринг, телеграм-бот, Яндекс API, яндекс.модуль, яндекс.станция

На Яндекс.Станции неудобно смотреть YouTube. Нет рекомендаций, подписок и даже поиск нормально не работает. Поэтому я написал телеграмм бота для отправки на неё любого видео.

Дорабатываем Яндекс.Станцию для просмотра YouTube - 1

Под катом история, как я это сделал несмотря на то, что официального открытого API нет.

С чего все началось?

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

У меня глупый (не smart) телевизор, а в качестве основной медиа приставки я использую Станцию. Все отлично, да только YouTube смотреть на ней совсем неудобно. Нельзя войти в аккаунт Ютуба, а значит, никаких рекомендаций и подписок. Кроме того, поиск по видео в Станции, как я понял, осуществляется через Яндекс.Видео. К сожалению такая схема не очень хорошо работает. Иногда не находятся видео даже если дословно произнести название, а новые видео вообще нельзя посмотреть, пока поисковик Яндекса их не проиндексирует.

Я почти смирился с тем, что YouTube на Станции смотреть нельзя, но все изменилось пару недель назад.

Что же произошло?

В субботу утром я решил посмотреть последний сезон «Кремниевой долины». Зашел на «Кинопоиск» и увидел следующее:

Дорабатываем Яндекс.Станцию для просмотра YouTube - 2

После клика по кнопке видео улетело на Яндекс.Станцию и воспроизвелось дальше там. Прямо как ChromeCast или AirPlay. Восторг! Но я обрадовался не самому функционалу, а потенциальной возможности отправить любое видео на станцию.

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

Давайте разбираться.

Открываем «Кинопоиск» или «Яндекс.Видео» в Хроме — там отличные инструменты для web разработки. Находим нужную кнопку, кликаем правой клавишей мыши, выбираем «Исследовать элемент».

Дорабатываем Яндекс.Станцию для просмотра YouTube - 3

Можно много, что там поизучать, но нас интересует, какой запрос выполняется при клике по этой кнопке. Переходим во вкладку «Network» инструментов разработчика и смотрим запросы.

Дорабатываем Яндекс.Станцию для просмотра YouTube - 4

Да, отлетает много статистики, но сразу видно 2 интересных запроса. Это devices_online_stats и station.

Получаем список устройств

devices_online_stats — запрос активных устройств пользователя. Простой GET запрос. Если вы авторизованы в Яндексе, то можете узнать о своих устройствах просто открыв в браузере ссылку:

quasar.yandex.ru/devices_online_stats

Что в ответе:

{  
   "items":[  
      {  
         "icon":"https://avatars.mds.yandex.net/get-yandex-station/1540981/yandexstationicon/orig",
         "id":"************",
         "name":"Яндекс Станция",
         "online":true,
         "platform":"yandexstation",
         "screen_capable":true,
         "screen_present":true
      }
   ],
   "status":"ok"
}

Интересно и достаточно интуитивно. ID Станции в примере я заменил на звездочки на всякий случай, но именно он понадобится нам в дальнейшем.

Воспроизводим видео

Запрос на yandex.ru/video/station отправляется методом POST. Повторим его из консоли, получив команду следующим образом:

Дорабатываем Яндекс.Станцию для просмотра YouTube - 5

Запускаем в терминале и получаем ответ:

{
  "status": "play",
  "msg": "success",
  "code": 1
}

Через пару секунд видео запускается на станции. Успех!

Собираем

Я удалил все «лишние» поля из запроса так, чтобы он остался рабочим. Для отправки видео на Станцию в тело и заголовки POST запроса нужно положить всего 4 параметра:

  • SessionID — авторизация в Яндексе
  • x-csrf-token
  • provider_item_id — ссылка на видео (или идентификатор для некоторых сервисов)
  • device — Идентификатор устройства, который мы получили ранее

Что за x-csrf-token? Не будем сейчас углубляться. Его можно получить просто GET запросом на frontend.vh.yandex.ru/csrf_token если вы авторизованы в Яндексе.

К этому моменту я уже стал оборачивать все в скрипт на Python. В итоге функция для отправки видео на станцию выглядит примерно так:

def sendToScreen(video_url):

    # Auth and getting Session_id

    auth_data = {
            'login': config.login, 
            'passwd': config.password
            }

    s = requests.Session()
    s.get("https://passport.yandex.ru/")
    s.post("https://passport.yandex.ru/passport?mode=auth&retpath=https://yandex.ru", data=auth_data)
    
    Session_id = s.cookies["Session_id"]
    
    # Getting x-csrf-token
    token = s.get('https://frontend.vh.yandex.ru/csrf_token').text

    # Getting devices info TODO: device selection here
    devices_online_stats = s.get("https://quasar.yandex.ru/devices_online_stats").text
    devices = json.loads(devices_online_stats)["items"]

    # Preparing request
    headers = {
        "x-csrf-token": token,
    }

    data = {
        "msg": {
            "provider_item_id": video_url
        },
        "device": devices[0]["id"]
    }

    if "https://www.youtube" in video_url:
        data["msg"]["player_id"] = "youtube"

    # Sending command with video to device
    res = s.post("https://yandex.ru/video/station", data=json.dumps(data), headers=headers)

    return res.text

Вы могли заметить, что я добавляю поле player_id если прислана ссылка с Ютуба. Дело в том, что на Станции есть несколько плееров с кодами youtube, vh и ott. По умолчанию используется vh, но тогда ломается превью и название ролика. Кроме того, его состояние не сбрасывается при смене ролика, что часто вызывает ошибки (Возможно, не все поля в запросе были «лишними»). Плеер ott, как я понял, используется для стриминговых сервисов, а это значит, что в перспективе можно смотреть IPTV через станцию.

Что в итоге?

Сейчас у меня есть бот, через которого мы отправляем видео с Ютуба на Станцию. Просто нажимаем «Поделиться» в приложении YouTube и отправляем ссылку Боту. Кстати, я назвал его «Ящик» и сделал логотип).

Дорабатываем Яндекс.Станцию для просмотра YouTube - 6

Я не стал делать его публичным, чтобы не собирать логины и пароли. Но вы можете развернуть такого же для себя или доработать для OAuth авторизации или отправки видео с других сайтов. Все исходники доступны на GitHub.

Я хотел сделать расширение для браузера, чтобы работало совсем как AirPlay с любыми видео, но понял, что удобнее отправлять из приложения с телефона. А для такого сценария лучше подходит бот. Вот видео его работы:

Заключение

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

Разработчики Яндекса, пожалуйста не ломайте этот запрос. Это не уязвимость. Работает только с аутентификацией. А если есть возможность — сделайте API устройств публичным — столько всего можно еще сделать!

Спасибо, что читаете мои статьи! Надеюсь, вам было интересно.

Успехов!

Автор: Krupnikas

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js