Skip to content

Instantly share code, notes, and snippets.

@probonopd
Last active April 17, 2020 00:54
Show Gist options
  • Save probonopd/9893084d982893c4c7b7 to your computer and use it in GitHub Desktop.
Save probonopd/9893084d982893c4c7b7 to your computer and use it in GitHub Desktop.
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>&lt;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/"&gt;&lt;item id="f-0" parentID="0" restricted="0"&gt;&lt;dc:title&gt;Video&lt;/dc:title&gt;&lt;dc:creator&gt;vGet&lt;/dc:creator&gt;&lt;upnp:class&gt;object.item.videoItem&lt;/upnp:class&gt;&lt;res protocolInfo="http-get:*:video/mp4:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000" sec:URIType="public"&gt;$URI&lt;/res&gt;&lt;/item&gt;&lt;/DIDL-Lite&gt;</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"
@probonopd
Copy link
Author

No, I had cobbled this together myself.

@probonopd
Copy link
Author

Definitely still works with online streams including YouTube.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment