Тема: Передача ссылки по DLNA на воспроизведение файла по сети
Как-то, в одной теме, задавали вопрос по поводу почему телевизор не отображает название отправившего ему файл устройства.
Мне вот самому было интересно разобраться бы как работает это всё DLNA и я даже начал пробовать всё это изучить на низком уровне, попробовать отсылать сообщение и вообще посмотреть - как это всё работает.
Я подключал свой телефон к Wi-Fi через прокси, который был Charles и там просматривал как общаются между собой устройства и телевизор.
Написал маленькую программку, которая бы в точности повторяла подобные действия и могла общаться с телеком, а именно посылать ему команды Stop, "Установить ссылку на файл" и Play. Также подключал свой телевизор к сети также через прокси и смотрел.
И у меня даже получилось. Начал читать LDNA спецификацию и прочее. Надо сказать, что мне пришлось умерить пыл и свои скачущие мысли от потуг написать что-то типа мини DLNA сервера, который бы мог быть виден телевизором, встроенным HTTP сервером, и вообще.. Но, подумал, что меня явно тут посчитают неадекватом, который из-за лени писать код скриптов пишет HMSEditor, а чтобы разобраться как работает DLNA, пишет медиа-сервер...
Так вот что мне стало интересно. Дело в том, что на моём телеке в программе Домашний медиа-сервер ну напрочь никак не получалось использовать возможности таких настроек, как "Оригинальная ссылка", "Оригинальная ссылка (перенаправление)" и "Оригинальный поток".
При включении данных настроек у меня в телевизоре перестают отображаться ссылки на видео. Только папки.
Поэтому как-то давно я уже успокоился и решил, что мой телевизор данный режим просто не поддерживает и завидовал людям, которые этим пользуются.
Но тут, написав программку, которая может отсылать файл телеку, причём через себя никакого потока не передавая, а просто указав ссылку на сторонний http ресурс, понимаю - что мой телек прекрасно это воспроизводит! Т.е. по сути - эта самая фича - передача телевизору оригинальной ссылки. А он уже без участия кого-либо спокойно проигрывает файл из интернета.
Мне стало интересно и даже появилась надежда, что всё-таки можно настроить мой телек и HMS на такую работу.
Я написал маленькую программку, которая может отсылать телеку ссылку на файл и дать ему команду проиграть его.
Т.к. при включении устройства оно в сети создаёт свой http сервер, порт работы может устанавливаться разный и отличаться от случая к случаю.
Поэтому для начала посылается широковещательный UDP запрос в локальную сеть по адресу
239.255.255.250:1900 с определёнными заголовками:
M-SEARCH * HTTP/1.1
HOST:239.255.255.250:1900
MAN:"ssdp:discover"
ST:upnp:rootdevice
MX:3
USER-AGENT: unix/5.1 UPnP/1.0 testdlna/1.0
В течении где-то 3-х секунд устройства в сети должны ответить и сообщить о своём существовании.
Где в заголовках ответа мы можем узнать их LOCATION - ссылку на xml с описанием устройства и его сервисов (типа может проигрывать файлы и проч). А также заодно и узнать по какому порту он в данный момент работает.
Сходив по этой ссылке узнаём всё о сервисах и какие параметры нужно передавать, чтобы отдавать команды.
В нашем случае, используется только сервис "AVTransport", который как раз отвечает за удалённую установку ссылки и команды Stop, Play, GetCurrentPosition или типа того.
Теперь при общении с устройством в заголовках запроса добавляем поле "SOAPACTION" с указанием сервиса и команды.
Также передаём дополнительную информацию в виде XML, где указывает параметры в зависимости от команды.
В случае указания файла, который ему нужно проиграть, также добавляется DIDL-Lite сообщение в формате xml, где описываются формат(ы) файла(ов) передаваемые телеку - его MIME-тип, имя, длительность, размер и проч.
Первым параметром в моей программке указывается IP адрес устройства, на который хотим послать файл.
Если никаких других параметров установлено не было, то будет послан файл, который зашит в самой программе (какая-то реклама)
Пример использования:
testdlna.exe 192.168.1.20
или
testdlna.exe 192.168.1.20 -f "http://pw22.poiuytrew.pw/s/44684c4f59a2 … 03_480.mp4"
Также есть ключ "-d". Если будет установлен - будет создаваться файл "testdlna.exe.log", где будут подробно запротоколированы все ответы от устройства.
Вместо 192.168.1.20 нужно указывать IP своего телевизора. Но можно и указать ключевое слово, которое точно его идентифицирует (ищет в ответах).
Например, в моём случае, можно даже так:
testdlna.exe sony -d
Первые несколько секунд в сети будут искаться устройства. Потом, если найдено нужное, ему будут отправлены три команды:
Stop, SetAVTransportURI и Play.
Также, для пущих экспериментов, сделал возможность указывать ссылку на youtube, например:
testdlna.exe sony -d -f "http://www.youtube.com/watch?v=25pzrnf8xyk"
Программка сама получить ссылку на реальный видео файл и попытается его отправиться телеку.
Но что с Sony?
А вот что. Если встроенная ссылка нормально показывается на моём телевизоре, то практически все другие - отказывается. Проанализировав заголовки запросов и ответов я пришёл и удивительным выводам.
Посылаем телеку ссылку:
http://cxz.to/get/dl/6fmpm2g2rmr6147s8u1ot8txa.0.1139013157.2185543202.1447516225/American.Ultra.2015.D.BDRip.1080p.360.mp4
Телек:
HEAD /get/dl/6fmpm2g2rmr6147s8u1ot8txa.0.1139013157.2185543202.1447516225/American.Ultra.2015.D.BDRip.1080p.360.mp4 HTTP/1.1
getcontentFeatures.dlna.org: 1
Pragma: getIfoFileURI.dlna.org
X-AV-Physical-Unit-Info: pa="BRAVIA KDL-32CX523";
X-AV-Client-Info: av=5.0; cn="Sony Corporation"; mn="BRAVIA KDL-32CX523"; mv="1.7";
Host: 54.194.29.154:80
HTTP/1.1 403 Forbidden
Server: nginx
Date: Sat, 14 Nov 2015 16:25:20 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Стоп! 54.194.29.154:80? Это он имя cxz.to зарезолвил в IP и по нему стал обращаться. Но обломался. А почему?
Сделаем запрос через браузер ссылке выше, ответ такой:
HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Sat, 14 Nov 2015 16:28:13 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Location: http://filecdn.to/fsuaget/MWUyZTgzZDlkY2U0NzhjMjY1ZGM4NzQ3MGYxOGFmOGFmc3RvfDM5NjgyMzg1fDEwMDAwfDB8MHx8NDE2YjM3ZWUxZjM5ZDZlODMwOTgyNTA3OGM2NWNmMDh8MXwxNDQ3NTE4NDkz/American.Ultra.2015.D.BDRip.1080p.360.mp4
Т.е. перенаправление на совсем другой ресурс с другой ссылкой.
А телек сделал тупо - перенаправление игнорирует (не умеет) и запрашивает по ip со старым значением запроса.
Ок. Сделаем это за него и посмотрим куда ведёт эта ссылка и отдадим телеку уже команду проиграть окончательную ссылку после всех перенаправлений:
http://n25.filecdn.to/ff/MWUyZTgzZDlkY2U0NzhjMjY1ZGM4NzQ3MGYxOGFmOGF8ZnN0b3wzOTY4MjM4NXwxMDAwMHwwfDB8bnwyNXxhZWJjNDVhZTJjMzc4ZmM0MzlmYzhmNmZkNDVkMWQxMXwxfDI2OnEuMzY6ZXwwfDgzMjUyNDU2OHwxNDQ3NTE5MDU3LjM4NDI,/American.Ultra.2015.D.BDRip.1080p.360.mp4
И что вы думаете? Это странное устройство стало запрашивать файл:
http://91.226.97.25/ff/MWUyZTgzZDlkY2U0NzhjMjY1ZGM4NzQ3MGYxOGFmOGF8ZnN0b3wzOTY4MjM4NXwxMDAwMHwwfDB8bnwyNXxhZWJjNDVhZTJjMzc4ZmM0MzlmYzhmNmZkNDVkMWQxMXwxfDI2OnEuMzY6ZXwwfDgzMjUyNDU2OHwxNDQ3NTE5MDU3LjM4NDI,/American.Ultra.2015.D.BDRip.1080p.360.mp4
где и обламывается. Потому как на одном IP могут находится много серверов и они, естественно смотрят, куда именно идёт запрос. И только редкие на уникальном ip, которым всё равно - будут правильно отдавать файл.
Итого, выводы:
Телек Sony - не умеет работать с перенаправлениями (ответы 301-303) и делает запрос всегда по IP, а не по доменному имени.
Отсюда великие обломы.
1) Почти любой сервер с хранением медиа-контента работает с CDN - распределением нагрузки и перенаправляет трафик - для Sony облом.
2) Почти никто из серверов не хочет отдавать контент по указанному конкретному адресу, а работает с доменным именем и смотрит на какой именно пришёл запрос - для Sony облом.
Грустно. Решил поделиться. Исходники проги.
Думаю, с другими телевизорами таких проблем нет.
Файл testdlna.exe прикреплён в сообщении ниже.