[DLNA] Debugging a UPnP / DLNA Media Server

Talk about the Ultimate Question of Life, The Universe, and Everything
Post Reply
User avatar
rednoah
The Source
Posts: 23216
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

[DLNA] Debugging a UPnP / DLNA Media Server

Post by rednoah »

:idea: First and foremost, please use the dlna.groovy script to discover all the media servers on the local network and to print the content directory tree for inspection and debugging purposes:

Shell: Select all

filebot -script fn:dlna --output ./Result
(requires FileBot r10323 or higher)




:idea: Here's how a DLNA client connects to a DLNA media server:

  1. 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
    
  2. 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
    
  3. 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>
    
  4. 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>
    
  5. 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>&lt;DIDL-Lite ... &lt;/DIDL-Lite&gt;</Result>
    			<NumberReturned>3</NumberReturned>
    			<TotalMatches>3</TotalMatches>
    			<UpdateID>10</UpdateID>
    		</u:BrowseResponse>
    	</s:Body>
    </s:Envelope>
    
  6. 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>
    
  7. 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.







:arrow: 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>
:idea: Please read the FAQ and How to Request Help.
Post Reply