Shell: Select all
filebot -script fn:dlna --output ./Result
Here's how a DLNA client connects to a DLNA media server:
- Use SSDP (Simple Service Discovery Protocol) to send a M-SEARCH * HTTP/1.1 request to every device on the local network:
http: Select all
M-SEARCH * HTTP/1.1 HOST: 239.255.255.250:1900 MAN: "ssdp:discover" MX: 5 ST: urn:schemas-upnp-org:device:MediaServer:1
- Each media server on the network will then respond with the LOCATION of its device descriptor:
http: Select all
HTTP/1.1 200 OK ... LOCATION: http://192.168.0.10:50001/desc/device.xml ... ST: urn:schemas-upnp-org:device:MediaServer:1
- The device descriptor will then tell us the controlURL of the ContentDirectory service:
xml: Select all
<root xmlns="urn:schemas-upnp-org:device-1-0"> ... <device> <deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType> <modelDescription>Synology DLNA/UPnP Media Server</modelDescription> ... <serviceList> ... <service> <serviceType>urn:schemas-upnp-org:service:ContentDirectory:1</serviceType> ... <controlURL>/ContentDirectory/control</controlURL> ... </service> </serviceList> </device> </root>
- We can then send a SOAP request for ObjectID=0 (i.e. root directory) to the controlURL via a HTTP POST request:
Shell: Select all
curl "http://192.168.0.10:50001/ContentDirectory/control" -A "DLNADOC/1.50" \ -H 'SOAPACTION: "urn:schemas-upnp-org:service:ContentDirectory:1#Browse"' \ -H 'Content-Type: text/xml; charset="utf-8"' -d '<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1"><ObjectID>0</ObjectID><BrowseFlag>BrowseDirectChildren</BrowseFlag><StartingIndex>0</StartingIndex><RequestedCount>100</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>'
http: Select all
POST /ContentDirectory/control HTTP/1.1 HOST: 192.168.0.10:50001 ... SOAPACTION: "urn:schemas-upnp-org:service:ContentDirectory:1#Browse" USER-AGENT: DLNADOC/1.50
xml: Select all
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1"> <ObjectID>0</ObjectID> <BrowseFlag>BrowseDirectChildren</BrowseFlag> <Filter>*</Filter> <StartingIndex>0</StartingIndex> <RequestedCount>5000</RequestedCount> <SortCriteria></SortCriteria> </u:Browse> </s:Body> </s:Envelope>
- The SOAP response will give us the Result as XML text element:
xml: Select all
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:BrowseResponse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1"> <Result><DIDL-Lite ... </DIDL-Lite></Result> <NumberReturned>3</NumberReturned> <TotalMatches>3</TotalMatches> <UpdateID>10</UpdateID> </u:BrowseResponse> </s:Body> </s:Envelope>
- After decoding and parsing the Result element as XML we can now see the root directory listing:
xml: Select all
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:sec="http://www.sec.co.kr/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/"> ... <container id="33" parentID="0" restricted="1"> <dc:title>Video</dc:title> <upnp:class>object.container.storageFolder</upnp:class> </container> </DIDL-Lite>
- Each directory listing will tell us the container id for each subfolder, so we can then recursively request and traverse the entire folder structure on the media server.
Let's have a look at a specific directory listing for a video folder that a DLNA client might be working with:
Console Output: Select all
$ filebot -script fn:dlna --output ./Result --q "33" --db "http://192.168.0.10:50001/desc/device.xml"
[ObjectID=33$@3286] The Man from Earth (2007)
└─ albumArtURI [profileID=JPEG_TN] http://192.168.0.10:50002/transcoder/jpegtnscaler.cgi/vfolderart/3286.jpg
└─ res [duration=1:27:11.000, nrAudioChannels=6, protocolInfo=http-get:*:video/x-matroska:DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01700000000000000000000000000000, sampleFrequency=48000, size=9756560873, bitrate=1864868, resolution=1920x1080] http://192.168.0.10:50002/v/NDLNA/3286.mkv
└─ res [protocolInfo=http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_FLAGS=00f00000000000000000000000000000] http://192.168.0.10:50002/transcoder/jpegtnscaler.cgi/vfolderart/3286.jpg
xml: Select all
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:sec="http://www.sec.co.kr/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/">
<item id="33$@3286" parentID="33" restricted="1">
<dc:title>The Man from Earth (2007)</dc:title>
<upnp:class>object.item.videoItem</upnp:class>
<dc:date>2024-06-14T00:00:00</dc:date>
<upnp:albumArtURI dlna:profileID="JPEG_TN">http://192.168.0.10:50002/transcoder/jpegtnscaler.cgi/vfolderart/3286.jpg</upnp:albumArtURI>
<res protocolInfo="http-get:*:video/x-matroska:DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01700000000000000000000000000000" resolution="1920x1080" size="9756560873" bitrate="1864868" duration="1:27:11.000" nrAudioChannels="6" sampleFrequency="48000">http://192.168.0.10:50002/v/NDLNA/3286.mkv</res>
<res protocolInfo="http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_FLAGS=00f00000000000000000000000000000">http://192.168.0.10:50002/transcoder/jpegtnscaler.cgi/vfolderart/3286.jpg</res>
</item>
</DIDL-Lite>