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

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



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

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


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

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

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

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


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


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

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

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


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


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


    Да, отлетает много статистики, но сразу видно 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. Повторим его из консоли, получив команду следующим образом:


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

    {
      "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 и отправляем ссылку Боту. Кстати, я назвал его «Ящик» и сделал логотип).


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

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


    Заключение


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

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

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

    Успехов!
    Поддержать автора
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 28

      +8
      Блин, это именно то чего мне не хватало в яндекс станции! Точно так же страдал. Спасибо!
        +5

        Пользуйтесь! Здорово, что кому-то пригодилось)

          0
          нужен сервант для бота, так-то буду
          +2

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

          0
          И мне, как я раньше не додумался проверить функцию «поделиться».
          Яндекс, не ломайте пожалуйста, у меня теперь есть повод отдать ползарплаты за вашу Станцию.
          Хотя конечно матери моей нативный YouTube был бы лучше, рекомендации ей помогли бы найти интересный ей контент
          +4
          Вот еще бы со звуком так, для мини станций. Тогда можно было б уведомления от умного дома кидать
            0
            В Яндекс.Музыке есть кнопка «Слушать на Станции», так что это теоретически возможно. Нужно разобраться только, есть ли там плеер, который сможет проиграть трек по произвольной ссылке.
              0

              Интересная идея! Попробую)

                0

                Спасибо, сделать звук было бы отлично!

              +1
              Правильно ли я понял, что если немного докрутить настройки, дома поднять http-сервер, то можно в video_url подставлять локальную ссылку на файл, и так транслировать фильмы на станцию?
                0

                Я Хотел так сделать. Попробовал на своем публичном сервере разместить видео, и отправил ссылку на станцию. Не сработало. Но думаю, что если поэкспериментировать с форматами видео и настройками сервера, то может сработать.

                  0

                  У меня не получилось скормить колонке локальные mp3 и mp4, в ответ приходит ошибка. Если завернуть mp4 в самый простой web-плеер, то в ответ приходит success, но колонка моргает красным и ничего не показывает. Нужно найти правильные форматы.

                    0
                    У Вас получилось что-то? А то я сколько не пытаюсь это сделать, всё ошибка приходит «cant play video»
                  +1

                  Расширение для браузера на пк и андроид: https://chrome.google.com/webstore/detail/yastation-cast/kgikiadkcnpogmbomapbkmcpmdknjbjj
                  Приложение для андроид с точно таким же методом отправки:
                  https://play.google.com/store/apps/details?id=org.sitx.ycast

                    0
                    Ну да, то что для андроида мое.
                      0
                      в Казахстане Google play пишет «недоступно в вашей стране» для приложения на Андроид. можно ли устранить подобную дискриминацию?
                      0
                      Мы с одним моим знакомым ещё давно выяснили, что у яндекс станции внутри на самом деле андроид, но USB-порт так и не нашли. Всё-таки интересно, возможно ли как-нибудь её дореверсить до того, чтобы можно было подключиться по adb и запускать андроидные приложения.
                        +1
                        А зачем с каждой ссылкой делается логин? Почему нельзя делать логин раз в сутки, например, и хранить детали сессии?
                          0
                          Да, так было бы правильнее сделать. Дело в том, что я пока не выяснил, как долго сессионный ключ остается валидным. Действительно, релогин можно делать только в случае, если ключ заэкспайрился и запрос не выполнился.

                          А еще я пока продолжаю эксперименты с этой функцией вне проекта с ботом. Поэтому мне удобнее, чтобы пока работало так.
                          +1

                          Топ! Тоже попробую, спасибо

                            0

                            Давно хочу поставить свой сервер на Raspberry Pi в квартире, чтобы можно было произвольное видео смотреть. Похоже появилась надежда.


                            Главное не злоупотреблять — если популяризовать эту историю, Яндекс может быстро прикрыть такое простое API :)

                              0

                              Есть открытый сервер для стрима. Туда можно RTSP стрим затащить или стримить видео из файла. https://github.com/mpromonet/webrtc-streamer

                              0
                              Нужно сделать Apple Shortcut, чтобы в него отправлять ссылку без бота. На днях станция приедет, попробую реализовать. Спасибо за разбор метода!
                                0
                                Собрал быструю команду для iOS. Тестировал в версии 13.3. Добавляем и заполняем логин, пароль своего аккаунта яндекс. После добавления команда появится в меню «поделиться». Открываем приложение YouTube, жмем поделиться на видео, «More» и нажимаем на YStation Video.
                                Все сделано на запросах в яндекс, пароль и логин хранятся только в команде после ее добавления. Можно доработать и вынести в отдельный файл.
                                www.icloud.com/shortcuts/fc0addb77bcf4592b7209fa724a6b573

                                Кстати, в источниках не увидел где используется кука Session_id и у меня без нее заработало.
                                0
                                Добрый день, спасибо вам за работу. Я глянул исходники на гитхабе, и, насколько я понял, вы используете опрос телеграм API через какое-то время, веб-хуки не используются.
                                Есть очень интересная штука — называется Google Apps Script. Там вы можете написать всю логику, а самое главное, что данное приложение в гугле можно опубликовать по опредленному УРЛ, и прописать его в веб-хуки телеграма. Таким образом, мы можем не держать у себя работающее железо со скриптами, нужен только смартфон с телегой и сама я.станция. Определенное количество запросов в сутки гугл даёт бесплатно, их с лихвой хватает для личного использования. Таким образом мы получаем личного телеграм бота, на инфраструктуре гугла и ещё и бесплатно! Схема работы такая: пишите боту — телеграм ломится в гугл — гугл отправляет урл в апи яндекса. Вот хорошая статья по теме: ocordova.me/blog/telegram-bot-with-apps-script

                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                Самое читаемое