find and control DLNA devices

v1.0.0

Use when controlling DLNA/UPnP media renderers (smart TVs, speakers) on a local network - discovering devices, playing media URLs, controlling playback (play...

0· 73·0 current·0 all-time
bydxs@dxsdyhm

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for dxsdyhm/dlna.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "find and control DLNA devices" (dxsdyhm/dlna) from ClawHub.
Skill page: https://clawhub.ai/dxsdyhm/dlna
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install dlna

ClawHub CLI

Package manager switcher

npx clawhub@latest install dlna
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
Name/description align with the content: the SKILL.md describes SSDP discovery and AVTransport control using async_upnp_client and related libraries. Required capabilities (network access to LAN devices) are appropriate for DLNA control.
Instruction Scope
Runtime instructions focus on network discovery and SOAP control of MediaRenderer devices (discover, SetAVTransportURI, Play, Pause, etc.). They do not ask to read unrelated files, access unrelated environment variables, or contact third-party endpoints outside normal DLNA flows.
Install Mechanism
This is an instruction-only skill with no install spec or code files. The declared Python dependencies (async_upnp_client, httpx, click) are reasonable and proportional to the task; there is no arbitrary download or extract step.
Credentials
No environment variables, credentials, or config paths are requested. The skill's need for local network access (SSDP/UDP 1900 and HTTP to devices) is expected for DLNA control.
Persistence & Privilege
Skill does not request persistent/always-on privileges and is user-invocable only. It does not modify other skills or system-wide configs.
Assessment
This skill appears coherent and focused on DLNA/UPnP control, but consider the following before installing: (1) It requires local network access—SSDP discovery will probe the LAN (UDP 1900); run it only on trusted networks. (2) Playing arbitrary media URLs causes your devices to fetch external content; avoid untrusted URLs to prevent exposing device/network metadata or serving malicious content. (3) The SKILL.md lists Python dependencies but includes no install automation—verify and pin dependency versions before installing. (4) If you need stronger isolation, run the code in a restricted environment or network segment that limits access to sensitive devices. If you want extra assurance, request the actual implementation code (not just instructions) and review it for unexpected network calls or file access.

Like a lobster shell, security has layers — review code before you run it.

latestvk975twfpaajtvk2c6vary69zsx84vhme
73downloads
0stars
1versions
Updated 2w ago
v1.0.0
MIT-0

DLNA/UPnP Control

Overview

Control DLNA/UPnP MediaRenderer devices (smart TVs, speakers) on the local network. Uses async_upnp_client library for SSDP discovery and SOAP-based device control.

When to Use

  • Need to discover and list DLNA devices on LAN
  • Play media URLs on smart TVs or DLNA speakers
  • Control playback (play, pause, stop, seek)
  • Query current transport/position status
  • Set default device for simplified operations
  • Build CLI or Python API for DLNA device control

Core Pattern

1. Device Discovery

from async_upnp_client import SsdpListener

async def discover_media_renderers(timeout: float = 5.0) -> list[DeviceInfo]:
    """Discover all MediaRenderer devices on network"""
    listener = SsdpListener()
    await listener.async_start()
    await asyncio.sleep(timeout)

    devices = []
    for usn, location in listener.unique_locations():
        device = await listener.async_get_device(location)
        if device and "MediaRenderer" in device.device_type:
            devices.append(DeviceInfo(
                name=device.friendly_name,
                udn=device.udn,
                location=location
            ))

    await listener.async_stop()
    return devices

2. Media Playback Control

from async_upnp_client import AsyncUPnPClient, AVTransport

async def play_media(device_url: str, media_url: str, title: str = None):
    """Play media URL on DLNA device"""
    async with httpx.AsyncClient() as client:
        device = await UPnPDevice.async_get_device(device_url, client=client)
        av_transport = device.service("urn:schemas-upnp-org:service:AVTransport:1")

        # Build DIDL-Lite metadata
        metadata = f'''<?xml version="1.0" encoding="utf-8"?>
        <DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/"
                   xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">
          <item id="0" parentID="0" restricted="0">
            <dc:title>{title or 'Media'}</dc:title>
            <res protocolInfo="http-get:*:video/mp4:*">{media_url}</res>
          </item>
        </DIDL-Lite>'''

        await av_transport.action("Stop", InstanceID=0)
        await av_transport.action("SetAVTransportURI", InstanceID=0, CurrentURI=media_url, CurrentURIMetaData=metadata)
        await av_transport.action("Play", InstanceID=0, Speed="1")

3. Transport Status Query

async def get_playback_status(av_transport) -> dict:
    """Query current playback state"""
    info = await av_transport.action("GetTransportInfo", InstanceID=0)
    position = await av_transport.action("GetPositionInfo", InstanceID=0)
    return {
        "state": info.get("CurrentTransportState"),  # PLAYING, PAUSED, STOPPED
        "position": position.get("RelTime"),
        "duration": position.get("TrackDuration")
    }

Quick Reference

ActionMethod
Discover devicesSsdpListener().unique_locations()
PlayAVTransport.action("Play", InstanceID=0, Speed="1")
PauseAVTransport.action("Pause", InstanceID=0)
StopAVTransport.action("Stop", InstanceID=0)
SeekAVTransport.action("Seek", InstanceID=0, Unit="REL_TIME", Target="01:00:00")
VolumeRenderingControl.action("SetVolume", InstanceID=0, DesiredVolume=50)
StatusAVTransport.action("GetTransportInfo", InstanceID=0)

Common Mistakes

IssueFix
SSDP timeoutIncrease timeout to 5-10s; check firewall allows UDP 1900
Play fails silentlyVerify media URL is accessible from TV network; check content type
Wrong content typeMatch protocolInfo to actual MIME type (video/mp4, audio/wav)
Device not foundUse exact UDN or IP:port from discovery; check device supports MediaRenderer

CLI Framework

Use Click for CLI:

import click
import asyncio

@click.group()
def cli():
    """DLNA/UPnP Media Controller"""
    pass

@cli.command()
@click.option("--timeout", "-t", default=5)
def discover(timeout):
    """Discover DLNA devices on network"""
    ...

@cli.command()
@click.argument("media_url")
@click.option("--device", "-d")
def play(media_url, device):
    """Play media URL"""
    ...

Dependencies

dependencies = [
    "async_upnp_client>=0.36.0",
    "click>=8.0.0",
    "httpx>=0.25.0",
]

Comments

Loading comments...