吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7183|回复: 34
收起左侧

[Python 原创] 简易DLNA投屏

  [复制链接]
Tonyha7 发表于 2025-1-31 20:39
图片.png

[Python] 纯文本查看 复制代码
import socket
from urllib.parse import urlparse
import requests
from xml.etree import ElementTree as ET

def find_devices():
    ssdp_request = (
        "M-SEARCH * HTTP/1.1\r\n"
        "HOST: 239.255.255.250:1900\r\n"
        "MAN: \"ssdp:discover\"\r\n"
        "MX: 2\r\n"
        "ST: urn:schemas-upnp-org:device:MediaRenderer:1\r\n"
        "\r\n"
    ).encode()

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
    sock.settimeout(3)
    sock.sendto(ssdp_request, ("239.255.255.250", 1900))

    locations = set()
    try:
        while True:
            data, _ = sock.recvfrom(4096)
            response = data.decode('utf-8', errors='ignore')
            for line in response.split('\r\n'):
                if line.lower().startswith('location:'):
                    location = line.split(':', 1)[1].strip()
                    locations.add(location)
    except socket.timeout:
        pass
    finally:
        sock.close()
    return list(locations)

def play(control_url, video_url):
    soap_action = "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI"
    headers = {
        "Content-Type": 'text/xml; charset="utf-8"',
        "SOAPAction": f'"{soap_action}"'
    }

    soap_body = f"""<?xml version="1.0" encoding="utf-8"?>
    <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>{video_url}</CurrentURI>
                <CurrentURIMetaData></CurrentURIMetaData>
            </u:SetAVTransportURI>
        </s:Body>
    </s:Envelope>"""

    try:
        response = requests.post(control_url, data=soap_body, headers=headers, timeout=5)
        response.raise_for_status()
        return True
    except Exception as e:
        print(f"投屏失败: {str(e)}")
        return False

def parse_device(location):
    try:
        response = requests.get(location, timeout=3)
        response.raise_for_status()
        root = ET.fromstring(response.content)
        
        device = root.find('.//{urn:schemas-upnp-org:device-1-0}device')
        if device is None:
            return None
            
        friendly_name = device.findtext('{urn:schemas-upnp-org:device-1-0}friendlyName', 'Unknown Device')

        url_parts = urlparse(location)
        base_url = f"{url_parts.scheme}://{url_parts.hostname}"
        if url_parts.port:
            base_url += f":{url_parts.port}"

        service = root.find('.//{urn:schemas-upnp-org:device-1-0}service'
                            '[{urn:schemas-upnp-org:device-1-0}serviceType'
                            '="urn:schemas-upnp-org:service:AVTransport:1"]')
        if service is None:
            return None

        control_path = service.findtext('{urn:schemas-upnp-org:device-1-0}controlURL')
        control_url = f"{base_url}{control_path}" if control_path else None

        return {
            'name': friendly_name,
            'control_url': control_url,
            'location': location
        }

    except Exception as e:
        print(f"Error parsing {location}: {str(e)}")
        return None

def main():
    print("正在扫描局域网中的DLNA设备...")
    locations = find_devices()
    
    if not locations:
        print("未找到任何DLNA设备")
        return

    devices = []
    for loc in locations:
        if dev_info := parse_device(loc):
            if not any(d['control_url'] == dev_info['control_url'] for d in devices):
                devices.append(dev_info)

    if not devices:
        print("未找到有效的投屏设备")
        return

    print("\n发现以下设备:")
    for idx, dev in enumerate(devices):
        print(f"[{idx+1}] {dev['name']}")

    try:
        choice = int(input("\n请输入设备编号: ")) - 1
        selected = devices[choice]
        print(f"\n已选择设备:{selected['name']}")
        print(f"控制地址: {selected['control_url']}")

        video_url = input("请输入要投屏的视频URL(支持常见流媒体格式): ").strip()

        if play(selected['control_url'], video_url):
            print(f"已发送投屏请求到 {selected['name']}")
        else:
            print("投屏请求失败")

    except (ValueError, IndexError):
        print("?")

if __name__ == "__main__":
    main()

免费评分

参与人数 6吾爱币 +13 热心值 +5 收起 理由
fcml45 + 1 + 1 热心回复!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
woyucheng + 1 + 1 谢谢@Thanks!
yanglinman + 1 + 1 谢谢@Thanks!
zpwz + 2 + 1 谢谢@Thanks!
lgc81034 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

LQ789 发表于 2025-2-4 14:08
试一下,希望自己能学着搞定,谢谢大佬
sgcj110 发表于 2025-2-1 20:35
东西挺不错的,好像前两年论坛里也有人分享过这种直接投屏到电视机的单个程序,不过不是很稳定,我后面是用了乐播投屏破解的,个人感觉还是挺不错的,界面相当简洁,投屏也非常的流畅
hanbazhen 发表于 2025-1-31 20:46
~楼主楼主,央视频4K投屏是什么协议?这个投不了
lakal 发表于 2025-1-31 21:06
感谢感谢
zpwz 发表于 2025-1-31 21:12
hanbazhen 发表于 2025-1-31 20:46
~楼主楼主,央视频4K投屏是什么协议?这个投不了

得装央视投屏助手
Arcticlyc 发表于 2025-1-31 21:21
这个不错,刚好学习一下 upnp 协议
hanbazhen 发表于 2025-1-31 21:25
zpwz 发表于 2025-1-31 21:12
得装央视投屏助手

那是什么协议,有谁做了出来
yjlxn 发表于 2025-1-31 21:29
谢谢楼主的无私分享
雨之幽 发表于 2025-1-31 22:12
任意播放??
crazyxsl 发表于 2025-1-31 23:13
可以的呢
ManaCola 发表于 2025-1-31 23:52
感谢楼主分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-4-17 10:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表