probonopd
6/7/2014 - 1:51 PM

Play a YouTube video on a Samsung Smart TV using UPNP

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"