Play a YouTube video on a Samsung Smart TV using UPNP
<?xml version="1.0" encoding="UTF-8"?>
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sec="http://www.sec.co.kr/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">
<item id="f-0" parentID="0" restricted="0">
<dc:title>Video</dc:title>
<dc:creator>vGet</dc:creator>
<upnp:class>object.item.videoItem</upnp:class>
<res protocolInfo="http-get:*:video/mp4:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000" sec:URIType="public">$URI</res>
</item>
</DIDL-Lite>
#!/bin/sh
#
# Download helper
#
if [ ! -e "/usr/local/bin/youtube-dl" ] ; then
sudo wget "https://yt-dl.org/downloads/latest/youtube-dl" -O /usr/local/bin/youtube-dl
sudo chmod a+x /usr/local/bin/youtube-dl
fi
#
# Determine URI
#
# URI="http://download.wavetlan.com/SVV/Media/HTTP/H264/Talkinghead_Media/H264_test1_Talkinghead_mp4_480x360.mp4"
if [ "${1:0:18}" == "http://www.youtube" ] ; then
echo "Parsing YouTube URL"
URI=$(youtube-dl -g "$1")
else
if [ "${1:0:4}" == "http" ] ; then
URI=$1
else
URI=$(youtube-dl -g --default-search "auto" "$1")
fi
fi
echo $URI
#
# Set URI
#
cat > /tmp/foo <<EOF
POST /smp_22_ HTTP/1.1
Accept: application/json, text/plain, */*
Soapaction: "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI"
Content-Type: text/xml;charset="UTF-8"
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
<InstanceID>0</InstanceID>
<CurrentURI>$URI</CurrentURI>
<CurrentURIMetaData><DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sec="http://www.sec.co.kr/"><item id="f-0" parentID="0" restricted="0"><dc:title>Video</dc:title><dc:creator>vGet</dc:creator><upnp:class>object.item.videoItem</upnp:class><res protocolInfo="http-get:*:video/mp4:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000" sec:URIType="public">$URI</res></item></DIDL-Lite></CurrentURIMetaData>
</u:SetAVTransportURI>
</s:Body>
</s:Envelope>
EOF
echo "==="
cat /tmp/foo | unix2dos | nc 192.168.0.13 7676
#
# Send PLAY
#
cat > /tmp/foo <<EOF
POST /smp_22_ HTTP/1.1
Accept: application/json, text/plain, */*
Soapaction: "urn:schemas-upnp-org:service:AVTransport:1#Play"
Content-Type: text/xml;charset="UTF-8"
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:Play xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
<InstanceID>0</InstanceID>
<Speed>1</Speed>
</u:Play>
</s:Body>
</s:Envelope>
EOF
echo "==="
cat /tmp/foo | unix2dos | nc 192.168.0.13 7676
# HTTP replay reverse engineering how to play a YouTube video on a Samsung Smart TV
# by controlling it over UPNP
# I used debian
sudo apt-get install tcpdump tcpslice tcptrace
mkdir replay
cd replay
# Capture packets (can also be done on the Mac)
tcpdump -i eth0 recorded.pcap
# Now run an application on the same computer that plays
# something on the Samsung TV
# I used vGet Cast (DLNA Controller)
# Convert to one file per HTTP session
tcpslice -w full.pcap recorded.pcap
tcptrace -e full.pcap
# Find the file to set the URL and replay it
FILE=$(grep -l -r SetAVTransportURI . | tail -n 1)
HOST=$(cat $FILE | grep "Host:" | cut -d " " -f 2 | sed -e 's|:| |g')
echo $FILE
cat $FILE | nc $HOST
# FIXME:
# If the TV was switched off before, I get "HTTP/1.1 412 Precondition Failed"
# Find the file to start Play and replay it
FILE=$(grep -l -r Play . | tail -n 1)
HOST=$(cat $FILE | grep "Host:" | cut -d " " -f 2 | sed -e 's|:| |g')
echo $FILE
cat $FILE | nc $HOST
###
unix2dos can be used to get "CRLF line terminators"