吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 10672|回复: 64
上一主题 下一主题
收起左侧

[Python 原创] [原码]虎牙直播收看器。任意直播源播放,不定期更新时,请看置顶贴

  [复制链接]
跳转到指定楼层
楼主
dltest 发表于 2022-10-16 23:39 回帖奖励
本帖最后由 dltest 于 2022-10-16 23:47 编辑

1输入虎牙房间ID号,不是网址中的号.
2点解析
3如果主播在线,默认播放地址为蓝光4M. 或者可以自己选择其它CDN及清晰度
4 播放
5.全屏快捷键 F11 ,或Esc键退出全屏
6 URL栏可以直播输入其它直播源地址,直接进行播放
7 代码编写环境 win7x64  python3.8

获取房间ID



本软件运行中截图


打包后的下载,如下。因本代码调用三方程序VLC所以同时打包了该程序约139M,测试环境win7x64
下载:https://wwz.lanzoub.com/i0n8F0e0biqf 密码:52pj




代码如下


[Python] 纯文本查看 复制代码
# -*- coding:utf-8 -*-
# @FileName  :huya_live_read.py
# @ Author   :dltest@52pojie
import json
import tkinter as tk
import tkinter.font as tkFont
from tkinter import *
from tkinter import ttk
import requests
import re
import os, platform
# 设置VLC库路径,需在import vlc之前
# os.environ['PYTHON_VLC_MODULE_PATH'] = "./vlc-3.0.6"
import vlc
class Player:
    '''
        args:设置 options
    '''

    def __init__(self, *args):
        if args:
            instance = vlc.Instance(*args)
            self.media = instance.media_player_new()
        else:
            self.media = vlc.MediaPlayer()

    # 设置待播放的url地址或本地文件路径,每次调用都会重新加载资源
    def set_uri(self, uri):
        self.media.set_mrl(uri)

    # 播放 成功返回0,失败返回-1
    def play(self, path=None):
        if path:
            self.set_uri(path)
            return self.media.play()
        else:
            return self.media.play()

    # 暂停
    def pause(self):
        self.media.pause()

    # 恢复
    def resume(self):
        self.media.set_pause(0)

    # 停止
    def stop(self):
        self.media.stop()

    # 释放资源
    def release(self):
        return self.media.release()

    # 是否正在播放
    def is_playing(self):
        return self.media.is_playing()

    # 已播放时间,返回毫秒值
    def get_time(self):
        return self.media.get_time()

    # 拖动指定的毫秒值处播放。成功返回0,失败返回-1 (需要注意,只有当前多媒体格式或流媒体协议支持才会生效)
    def set_time(self, ms):
        return self.media.get_time()

    # 音视频总长度,返回毫秒值
    def get_length(self):
        return self.media.get_length()

    # 获取当前音量(0~100)
    def get_volume(self):
        return self.media.audio_get_volume()

    # 设置音量(0~100)
    def set_volume(self, volume):
        return self.media.audio_set_volume(volume)

    # 返回当前状态:正在播放;暂停中;其他
    def get_state(self):
        state = self.media.get_state()
        if state == vlc.State.Playing:
            return 1
        elif state == vlc.State.Paused:
            return 0
        else:
            return -1

    # 当前播放进度情况。返回0.0~1.0之间的浮点数
    def get_position(self):
        return self.media.get_position()

    # 拖动当前进度,传入0.0~1.0之间的浮点数(需要注意,只有当前多媒体格式或流媒体协议支持才会生效)
    def set_position(self, float_val):
        return self.media.set_position(float_val)

    # 获取当前文件播放速率
    def get_rate(self):
        return self.media.get_rate()

    # 设置播放速率(如:1.2,表示加速1.2倍播放)
    def set_rate(self, rate):
        return self.media.set_rate(rate)

    # 设置宽高比率(如"16:9","4:3")
    def set_ratio(self, ratio):
        self.media.video_set_scale(0)  # 必须设置为0,否则无法修改屏幕宽高
        self.media.video_set_aspect_ratio(ratio)

    # 设置窗口句柄
    def set_window(self, wm_id):
        if platform.system() == 'Windows':
            self.media.set_hwnd(wm_id)
        else:
            self.media.set_xwindow(wm_id)

    # 注册监听器
    def add_callback(self, event_type, callback):
        self.media.event_manager().event_attach(event_type, callback)

    # 移除监听器
    def remove_callback(self, event_type, callback):
        self.media.event_manager().event_detach(event_type, callback)

class App:
    def __init__(self, root):
        self.editdate = '2022/10/17'
        self.root =root

        self.initUI(root)
        self.initData()
        self.player = Player()
        self.create_video_view(self.GLineEdit_621.winfo_id())
        self.root.bind("<F11>",self.changescreen)
        self.root.bind("<Escape>",self.exitfullscreen)

    def initData(self):
        self.GLineEdit_621.insert(0,'请输入直播间的ID')
        self.vol =50
        self.flag= True
        self.headers = {'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148'}
        self.api_url = 'https://mp.huya.com/cache.php?m=Live&do=profileRoom&roomid='

    def initUI(self,root):
        #setting title
        root.title(f"虎牙直播收看器 {self.editdate}  dltest@52pojie")
        #setting window size
        width=1244
        height=744
        screenwidth = root.winfo_screenwidth()
        screenheight = root.winfo_screenheight()
        alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
        root.geometry(alignstr)
        # root.resizable(width=False, height=False)


        self.GLineEdit_621=tk.Entry(root)
        self.GLineEdit_621["borderwidth"] = "1px"
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_621["font"] = ft
        self.GLineEdit_621["fg"] = "#333333"
        self.GLineEdit_621["bg"] = "#393d49"
        self.GLineEdit_621["justify"] = "center"
        self.GLineEdit_621["text"] = "ve"
        self.w =1243
        self.h =705
        self.GLineEdit_621.place(x=0,y=0,width=self.w,height=self.h)
        self.GLineEdit_621.bind('<Double-Button-1>',self.changescreen)

        self.GListBox_294=ttk.Combobox(root)
        ft = tkFont.Font(family='Times',size=10)
        self.GListBox_294["font"] = ft
        self.GListBox_294["justify"] = "center"
        self.GListBox_294.place(x=600,y=710,width=103,height=30)
        self.GListBox_294.bind("<<ComboboxSelected>>", self.choose)

        self.GLabel_149=tk.Label(root)
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_149["font"] = ft
        self.GLabel_149["fg"] = "#333333"
        self.GLabel_149["justify"] = "center"
        self.GLabel_149["text"] = "直播间ID:"
        self.GLabel_149.place(x=10,y=710,width=67,height=30)

        self.GLineEdit_15=tk.Entry(root)
        self.GLineEdit_15["borderwidth"] = "1px"
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_15["font"] = ft
        self.GLineEdit_15["fg"] = "#333333"
        self.GLineEdit_15["justify"] = "center"
        self.GLineEdit_15["text"] = "room_id"
        self.GLineEdit_15["relief"] = "groove"
        self.GLineEdit_15.place(x=80,y=710,width=83,height=30)

        self.GButton_246=tk.Button(root)
        self.GButton_246["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_246["font"] = ft
        self.GButton_246["fg"] = "#000000"
        self.GButton_246["justify"] = "center"
        self.GButton_246["text"] = "解析"
        self.GButton_246["relief"] = "groove"
        self.GButton_246.place(x=170,y=710,width=67,height=30)
        self.GButton_246["command"] = self.GButton_246_command

        self.GLabel_158=tk.Label(root)
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_158["font"] = ft
        self.GLabel_158["fg"] = "#333333"
        self.GLabel_158["justify"] = "center"
        self.GLabel_158["text"] = "选择清晰度:"
        self.GLabel_158.place(x=530,y=710,width=78,height=30)

        self.GLineEdit_316=tk.Entry(root)
        self.GLineEdit_316["borderwidth"] = "1px"
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_316["font"] = ft
        self.GLineEdit_316["fg"] = "#333333"
        self.GLineEdit_316["justify"] = "center"
        self.GLineEdit_316["text"] = "real_url"
        self.GLineEdit_316["relief"] = "groove"
        self.GLineEdit_316.place(x=450,y=710,width=80,height=30)

        self.GButton_701=tk.Button(root)
        self.GButton_701["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_701["font"] = ft
        self.GButton_701["fg"] = "#000000"
        self.GButton_701["justify"] = "center"
        self.GButton_701["text"] = "&#9658;播 放"
        self.GButton_701["relief"] = "groove"
        self.GButton_701.place(x=710,y=710,width=66,height=30)
        self.GButton_701["command"] = self.GButton_701_command

        self.GButton_132=tk.Button(root)
        self.GButton_132["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_132["font"] = ft
        self.GButton_132["fg"] = "#000000"
        self.GButton_132["justify"] = "center"
        self.GButton_132["text"] = "▍▍暂停"
        self.GButton_132["relief"] = "groove"
        self.GButton_132.place(x=780,y=710,width=66,height=30)
        self.GButton_132["command"] = self.GButton_132_command

        self.GButton_492=tk.Button(root)
        self.GButton_492["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_492["font"] = ft
        self.GButton_492["fg"] = "#000000"
        self.GButton_492["justify"] = "center"
        self.GButton_492["text"] = "&#11035; 停止"
        self.GButton_492["relief"] = "groove"
        self.GButton_492.place(x=850,y=710,width=66,height=30)
        self.GButton_492["command"] = self.GButton_492_command

        self.GButton_813=tk.Button(root)
        self.GButton_813["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_813["font"] = ft
        self.GButton_813["fg"] = "#000000"
        self.GButton_813["justify"] = "center"
        self.GButton_813["text"] = "音量 +"
        self.GButton_813["relief"] = "groove"
        self.GButton_813.place(x=940,y=710,width=66,height=30)
        self.GButton_813["command"] = self.GButton_813_command

        self.GButton_229=tk.Button(root)
        self.GButton_229["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_229["font"] = ft
        self.GButton_229["fg"] = "#000000"
        self.GButton_229["justify"] = "center"
        self.GButton_229["text"] = "音量 -"
        self.GButton_229["relief"] = "groove"
        self.GButton_229.place(x=1010,y=710,width=66,height=30)
        self.GButton_229["command"] = self.GButton_229_command

        self.GButton_316=tk.Button(root)
        self.GButton_316["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_316["font"] = ft
        self.GButton_316["fg"] = "#000000"
        self.GButton_316["justify"] = "center"
        self.GButton_316["text"] = "静 音"
        self.GButton_316["relief"] = "groove"
        self.GButton_316.place(x=1080,y=710,width=66,height=30)
        self.GButton_316["command"] = self.GButton_316_command

        self.GButton_275=tk.Button(root)
        self.GButton_275["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_275["font"] = ft
        self.GButton_275["fg"] = "#000000"
        self.GButton_275["justify"] = "center"
        self.GButton_275["text"] = "F11全屏"
        self.GButton_275["relief"] = "groove"
        self.GButton_275.place(x=1180,y=710,width=59,height=30)
        self.GButton_275["command"] = self.GButton_275_command

        self.GLineEdit_754=tk.Entry(root)
        self.GLineEdit_754["borderwidth"] = "1px"
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_754["font"] = ft
        self.GLineEdit_754["fg"] = "#333333"
        self.GLineEdit_754["justify"] = "center"
        self.GLineEdit_754["text"] = "zhubo_name"
        self.GLineEdit_754.place(x=290,y=710,width=153,height=30)

        self.GLabel_143=tk.Label(root)
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_143["font"] = ft
        self.GLabel_143["fg"] = "#333333"
        self.GLabel_143["justify"] = "center"
        self.GLabel_143["text"] = "主播名:"
        self.GLabel_143.place(x=240,y=710,width=57,height=30)

    def create_video_view(self,wid):
        self.player.set_window(wid)

    def choose(self,event):
        url = self.GListBox_294.get()
        self.GLineEdit_316.delete(0,'end')
        self.GLineEdit_316.insert(0,url.split('::')[1])

    #解析
    def GButton_246_command(self):
        self.GLineEdit_316.delete(0,'end')
        room_id = self.GLineEdit_15.get()
        if not room_id:
            return
        try:
            html = requests.get(self.api_url + room_id, headers=self.headers)
            data = json.loads(html.text)['data']
            nick = data['profileInfo']['nick']
            room_name = data['liveData']['roomName']
            liveStatus = data['liveStatus']
            print(f'{nick} {room_name} {liveStatus}')
        except:
            print('Room id is invalid!')
            self.GLineEdit_754.delete(0,'end')
            self.GLineEdit_754.insert(0,'房号错误!')
            return
        if liveStatus == "OFF":
            self.GLineEdit_754.delete(0,'end')
            self.GLineEdit_754.insert(0,f'未开播 {nick}')
            return f'{room_name} {nick} is offline'
        elif liveStatus == "REPLAY":
            self.GLineEdit_754.delete(0,'end')
            self.GLineEdit_754.insert(0,f'未开播 {nick}')
            return f'{room_name} {nick} is REPLAY'

        else:
            self.GLineEdit_754.delete(0,'end')
            self.GLineEdit_754.insert(0,f'【{nick}】{room_name}')
            stream_dict = data['stream']
            flv = stream_dict['flv']  # type: dict
            cdn = flv['multiLine']  # type: List
            rate = flv['rateArray']  # type: List
            supportable_resolution = {'原画': '', }
            for b in rate:
                supportable_resolution[b['sDisplayName']] = b['iBitRate']
            sort_dict = {}
            listbox = []
            for resolution, bitrate in supportable_resolution.items():
                url_list = []
                for i in cdn:
                    url = i['url'].replace('http://', 'https://')
                    url = url.replace(
                        'imgplus.flv', f'imgplus_{bitrate}.flv')
                    url_list.append(url)
                sort_dict[resolution] = url_list
            for resolution, url_list in sort_dict.items():
                count=0
                for i in url_list:
                    count += 1
                    listbox.append(f'【{resolution}】{count}::{i}')
        self.GListBox_294["values"] = listbox
        for i in listbox:
            if i.startswith('【蓝光4M】'):
                # self.GListBox_294.current(1)
                self.GListBox_294.set(i)
                self.GLineEdit_316.delete(0,'end')
                self.GLineEdit_316.insert(0,i.split('::')[1])
                break
        else:
            self.GListBox_294.current(1)
            self.GLineEdit_316.delete(0,'end')
            self.GLineEdit_316.insert(0,i.split('::')[1])


    def GButton_701_command(self): #&#9658;播 放
        url = self.GLineEdit_316.get().strip()
        if not url:
            return
        if self.player.get_state() == 0:
            self.player.resume()
        elif self.player.get_state() == 1:
            pass  # 播放新资源
            self.player.play(url)
        else:
            self.player.play(url)


    #暂停
    def GButton_132_command(self):
        self.player.pause()

    #停止
    def GButton_492_command(self):
        self.player.stop()

    #音量加
    def GButton_813_command(self):
        vol = self.player.get_volume()
        self.player.set_volume(vol+5)

    #音量减
    def GButton_229_command(self):
        vol = self.player.get_volume()
        self.player.set_volume(vol-5)

    #静音
    def GButton_316_command(self):
        vol = self.player.get_volume()
        if vol == 0:
            self.player.set_volume(self.vol)
        else:
            self.vol = self.player.get_volume()
            self.player.set_volume(0)

    #全屏
    def GButton_275_command(self):
        if  self.flag:
            self.root.attributes('-fullscreen',True)
            self.w, self.h = self.root.winfo_screenwidth(), self.root.winfo_screenheight()
            self.GLineEdit_621.place(x=0,y=0,width=self.w,height=self.h)
            self.GButton_492.place_forget()
            self.GLabel_149.place_forget()
            self.GLineEdit_15.place_forget()
            self.GButton_246.place_forget()
            self.GLabel_143.place_forget()
            self.GLineEdit_754.place_forget()
            self.GLineEdit_316.place_forget()
            self.GLabel_158.place_forget()
            self.GListBox_294.place_forget()
            self.GButton_701.place_forget()
            self.GButton_132.place_forget()
            self.GButton_492.place_forget()
            self.GButton_813.place_forget()
            self.GButton_229.place_forget()
            self.GButton_316.place_forget()
            self.GButton_275.place_forget()

        else:
            self.root.attributes('-fullscreen',False)
            # self.GLineEdit_621.place(x=0,y=0,width=self.w,height=self.h)
            self.GLineEdit_621.place(x=0,y=0,width=1243,height=705)
            self.GLabel_149.place(x=10,y=710,width=67,height=30)
            self.GLineEdit_15.place(x=80,y=710,width=83,height=30)
            self.GButton_246.place(x=170,y=710,width=67,height=30)
            self.GLabel_143.place(x=240,y=710,width=57,height=30)
            self.GLineEdit_754.place(x=290,y=710,width=153,height=30)
            self.GLineEdit_316.place(x=450,y=710,width=80,height=30)
            self.GLabel_158.place(x=530,y=710,width=78,height=30)
            self.GListBox_294.place(x=600,y=710,width=103,height=30)
            self.GButton_701.place(x=710,y=710,width=66,height=30)
            self.GButton_132.place(x=780,y=710,width=66,height=30)
            self.GButton_492.place(x=850,y=710,width=66,height=30)
            self.GButton_813.place(x=940,y=710,width=66,height=30)
            self.GButton_229.place(x=1010,y=710,width=66,height=30)
            self.GButton_316.place(x=1080,y=710,width=66,height=30)
            self.GButton_275.place(x=1180,y=710,width=59,height=30)

        self.flag = not self.flag



    def changescreen(self,event):
        self.GButton_275_command()

    def exitfullscreen(self,event):
        self.flag = True
        self.root.attributes('-fullscreen',False)
        self.GLineEdit_621.place(x=0,y=0,width=1243,height=705)
        self.GLabel_149.place(x=10,y=710,width=67,height=30)
        self.GLineEdit_15.place(x=80,y=710,width=83,height=30)
        self.GButton_246.place(x=170,y=710,width=67,height=30)
        self.GLabel_143.place(x=240,y=710,width=57,height=30)
        self.GLineEdit_754.place(x=290,y=710,width=153,height=30)
        self.GLineEdit_316.place(x=450,y=710,width=80,height=30)
        self.GLabel_158.place(x=530,y=710,width=78,height=30)
        self.GListBox_294.place(x=600,y=710,width=103,height=30)
        self.GButton_701.place(x=710,y=710,width=66,height=30)
        self.GButton_132.place(x=780,y=710,width=66,height=30)
        self.GButton_492.place(x=850,y=710,width=66,height=30)
        self.GButton_813.place(x=940,y=710,width=66,height=30)
        self.GButton_229.place(x=1010,y=710,width=66,height=30)
        self.GButton_316.place(x=1080,y=710,width=66,height=30)
        self.GButton_275.place(x=1180,y=710,width=59,height=30)


if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    root.mainloop()






免费评分

参与人数 7吾爱币 +9 热心值 +7 收起 理由
brostart + 1 + 1 这个解决了我的大问题,太感谢作者了。
jojaajj + 2 + 1 是否能添加“窗口总是最前”功能
z81192 + 1 + 1 谢谢@Thanks!
RUO + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
kololi + 1 + 1 我很赞同!
skiss + 1 + 1 谢谢@Thanks!
Stap + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

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

来自 #
 楼主| dltest 发表于 2022-10-24 23:07 |楼主
本次更新:
  • 重写UI
  • 可以自由缩放播放器大小
  • 加载虎牙分类菜单,方便快速找到喜欢的主播
  • 解析出来的主播,可以加入关注/收藏,点右侧列表快速加载
  • 其它


原功能仍保留
  • 可以自己输入房间号,进行解析、观看
  • 可以输入自定义直播间地址,观看


提醒
  • 返回选择类别或收藏界面,要先停止直播收看


程序目前尚存问题
1部份直播无法正常播放,例 娱乐天地/一起看 这个类型的直播基本都无法播放,语音类的无法正常显示等
2鼠标滚轮快捷调节音量,有时会失灵

打包好的exe文件下载(含vlc三方控件)
下载:https://wwz.lanzoub.com/iXbyS0ei3uja 密码:52pj





代码如下

[Python] 纯文本查看 复制代码
# -*- coding:utf-8 -*-
# @FileName  :huya_live_read.py
# @ Author   :dltest@52pojie
import json
import tkinter as tk
import tkinter.font as tkFont
from tkinter import *
from tkinter import ttk
import requests
import re
import os, platform
# 设置VLC库路径,需在import vlc之前
os.environ['PYTHON_VLC_MODULE_PATH'] = "./vlc-3.0.9.2-win64"
import vlc
from lxml import etree


class Player:
    '''
        args:设置 options
    '''

    def __init__(self, *args):
        if args:
            instance = vlc.Instance(*args)
            self.media = instance.media_player_new()
        else:
            self.media = vlc.MediaPlayer()

    # 设置待播放的url地址或本地文件路径,每次调用都会重新加载资源
    def set_uri(self, uri):
        self.media.set_mrl(uri)

    # 播放 成功返回0,失败返回-1
    def play(self, path=None):
        if path:
            self.set_uri(path)
            return self.media.play()
        else:
            return self.media.play()

    # 暂停
    def pause(self):
        self.media.pause()

    # 恢复
    def resume(self):
        self.media.set_pause(0)

    # 停止
    def stop(self):
        self.media.stop()

    # 释放资源
    def release(self):
        return self.media.release()

    # 是否正在播放
    def is_playing(self):
        return self.media.is_playing()

    # 已播放时间,返回毫秒值
    def get_time(self):
        return self.media.get_time()

    # 拖动指定的毫秒值处播放。成功返回0,失败返回-1 (需要注意,只有当前多媒体格式或流媒体协议支持才会生效)
    def set_time(self, ms):
        return self.media.get_time()

    # 音视频总长度,返回毫秒值
    def get_length(self):
        return self.media.get_length()

    # 获取当前音量(0~100)
    def get_volume(self):
        return self.media.audio_get_volume()

    # 设置音量(0~100)
    def set_volume(self, volume):
        return self.media.audio_set_volume(volume)

    # 返回当前状态:正在播放;暂停中;其他
    def get_state(self):
        state = self.media.get_state()
        if state == vlc.State.Playing:
            return 1
        elif state == vlc.State.Paused:
            return 0
        else:
            return -1

    # 当前播放进度情况。返回0.0~1.0之间的浮点数
    def get_position(self):
        return self.media.get_position()

    # 拖动当前进度,传入0.0~1.0之间的浮点数(需要注意,只有当前多媒体格式或流媒体协议支持才会生效)
    def set_position(self, float_val):
        return self.media.set_position(float_val)

    # 获取当前文件播放速率
    def get_rate(self):
        return self.media.get_rate()

    # 设置播放速率(如:1.2,表示加速1.2倍播放)
    def set_rate(self, rate):
        return self.media.set_rate(rate)

    # 设置宽高比率(如"16:9","4:3")
    def set_ratio(self, ratio):
        self.media.video_set_scale(0)  # 必须设置为0,否则无法修改屏幕宽高
        self.media.video_set_aspect_ratio(ratio)

    # 设置窗口句柄
    def set_window(self, wm_id):
        if platform.system() == 'Windows':
            self.media.set_hwnd(wm_id)
        else:
            self.media.set_xwindow(wm_id)

    # 注册监听器
    def add_callback(self, event_type, callback):
        self.media.event_manager().event_attach(event_type, callback)

    # 移除监听器
    def remove_callback(self, event_type, callback):
        self.media.event_manager().event_detach(event_type, callback)

class App:
    def __init__(self, root):
        self.root =root
        self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36'}
        self.editdate = '2022/10/24'
        self.init_ui(root)
        self.player = Player()
        self.create_video_view(self.frame_video.winfo_id())
        self.root.bind("<F11>",self.changescreen)
        self.root.bind("<Escape>",self.exitfullscreen)
        self.root.bind("<MouseWheel>",self.change_vol)
        self.flag= True
        self.choose_active(None)
        self.count = 0
        self.zhubo_list = self.getzhubolist()
        if not self.zhubo_list or len(self.zhubo_list) < 1:
            return
        self.anchor_list =[]
        self.settvlist(self.zhubo_list)

    def init_ui(self,root):
        #setting title
        root.title(f"虎牙直播收看器 {self.editdate}  dltest@52pojie")
        #setting window size
        width=578
        height=380
        screenwidth = root.winfo_screenwidth()
        screenheight = root.winfo_screenheight()
        alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
        root.geometry(alignstr)

        root.grid_rowconfigure(0,weight=1,minsize=40) # row为1,缩放比为1
        root.grid_columnconfigure(0,weight=1,minsize=40) # column为0,缩放比为1

        self.frame_main=tk.Frame(root, relief='groove' )
        self.frame_main.grid(row=0,column=0,sticky=NSEW)

        self.frame_video=tk.Frame(root, relief='groove' )
        self.frame_video['bg'] = "#ccc"
        self.frame_video.grid(row=0,column=0,sticky=NSEW)

        self.frame_main.tkraise()

        self.frame_buttom=tk.Frame(root, relief='groove')
        # self.frame_buttom['bg'] = "#ffffff"
        self.frame_buttom.grid(row=1,column=0,sticky=NSEW,padx=0, pady=0 ) # 跨2列

        self.GButton_274=tk.Button(self.frame_buttom)
        self.GButton_274["bg"] = "#efefef"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_274["font"] = ft
        self.GButton_274["fg"] = "#000000"
        self.GButton_274["justify"] = "center"
        self.GButton_274["text"] = "&#9658;"
        self.GButton_274["relief"] = "groove"
        # self.GButton_274.place(x=0,y=0,width=30,height=30)
        self.GButton_274.grid(row=0,column=0,sticky=NSEW,padx=5, pady=1 )
        self.GButton_274["command"] = self.GButton_274_command

        self.GButton_751=tk.Button(self.frame_buttom)
        self.GButton_751["bg"] = "#efefef"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_751["font"] = ft
        self.GButton_751["fg"] = "#000000"
        self.GButton_751["justify"] = "center"
        self.GButton_751["text"] = "▍▍"
        self.GButton_751["relief"] = "groove"
        self.GButton_751.grid(row=0,column=1,sticky=NSEW,padx=1, pady=1 )
        self.GButton_751["command"] = self.GButton_751_command

        self.GButton_159=tk.Button(self.frame_buttom)
        self.GButton_159["bg"] = "#efefef"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_159["font"] = ft
        self.GButton_159["fg"] = "#000000"
        self.GButton_159["justify"] = "center"
        self.GButton_159["text"] = "&#11035;"
        self.GButton_159["relief"] = "groove"
        self.GButton_159.grid(row=0,column=2,sticky=NSEW,padx=5, pady=1 )
        self.GButton_159["command"] = self.GButton_159_command

        self.GButton_991=tk.Button(self.frame_buttom)
        self.GButton_991["bg"] = "#efefef"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_991["font"] = ft
        self.GButton_991["fg"] = "#000000"
        self.GButton_991["justify"] = "center"
        self.GButton_991["text"] = "静音"
        self.GButton_991["relief"] = "groove"
        self.GButton_991.grid(row=0,column=3,sticky=NSEW,padx=5, pady=1 )
        self.GButton_991["command"] = self.GButton_991_command

        self.scint = IntVar()
        self.scint.set(50)
        self.GButton_79=tk.Scale(self.frame_buttom,from_=0,to=100,showvalue=False,tickinterval = 0,variable = self.scint,
                                 activebackground='#00ced1',orient=HORIZONTAL)
        self.GButton_79["bg"] = "#efefef"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_79["font"] = ft
        self.GButton_79["fg"] = "#000000"
        # self.GButton_79["justify"] = "center"
        # self.GButton_79["text"] = "音量控制"
        self.GButton_79["relief"] = "groove"
        self.GButton_79.grid(row=0,column=4,sticky=NSEW,padx=1, pady=1 )
        self.GButton_79["command"] = self.GButton_79_command

        self.GButton_39=tk.Button(self.frame_buttom)
        self.GButton_39["bg"] = "#efefef"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_39["font"] = ft
        self.GButton_39["fg"] = "#000000"
        self.GButton_39["justify"] = "center"
        self.GButton_39["text"] = "F11全屏"
        self.GButton_39["relief"] = "groove"
        self.GButton_39.grid(row=0,column=5,sticky=NSEW,padx=15, pady=1 )
        self.GButton_39["command"] = self.GButton_39_command

        #####################################################################################
        value = [('全部', '/g'), ('网游竞技', '/g_ol'), ('单机热游', '/g_pc'), ('娱乐天地', '/g_yl'), ('手游休闲', '/g_sy')]
        self.GLineEdit_678 = ttk.Combobox(self.frame_main, state='readonly')
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_678["font"] = ft
        self.GLineEdit_678["value"] = value
        self.GLineEdit_678.place(x=40,y=0,width=253,height=30)
        self.GLineEdit_678.bind("<<ComboboxSelected>>", self.choose_active)
        self.GLineEdit_678.current(0)


        self.GLabel_397=tk.Label(self.frame_main)
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_397["font"] = ft
        self.GLabel_397["fg"] = "#333333"
        self.GLabel_397["justify"] = "center"
        self.GLabel_397["text"] = "分 类"
        self.GLabel_397.place(x=0,y=0,width=30,height=30)

        self.GLabel_268=tk.Label(self.frame_main)
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_268["font"] = ft
        self.GLabel_268["fg"] = "#333333"
        self.GLabel_268["justify"] = "center"
        self.GLabel_268["text"] = "列 表"
        self.GLabel_268.place(x=0,y=40,width=30,height=30)

        self.GLineEdit_803=ttk.Combobox(self.frame_main, state='readonly')
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_803["font"] = ft
        self.GLineEdit_803.place(x=40,y=40,width=252,height=30)
        self.GLineEdit_803.bind("<<ComboboxSelected>>", self.choose_game)

        self.GLabel_354=tk.Label(self.frame_main)
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_354["font"] = ft
        self.GLabel_354["fg"] = "#333333"
        self.GLabel_354["justify"] = "center"
        self.GLabel_354["text"] = "在 播 "
        self.GLabel_354.place(x=0,y=80,width=30,height=30)

        self.GLineEdit_178=ttk.Combobox(self.frame_main, state='readonly')
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_178["font"] = ft
        self.GLineEdit_178.place(x=40,y=80,width=253,height=30)
        self.GLineEdit_178.bind("<<ComboboxSelected>>", self.choose_anchor)

        self.GButton_112=tk.Button(self.frame_main)
        self.GButton_112["bg"] = "#efefef"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_112["font"] = ft
        self.GButton_112["fg"] = "#000000"
        self.GButton_112["relief"] = "groove"
        self.GButton_112["justify"] = "center"
        self.GButton_112["text"] = "解析"
        self.GButton_112.place(x=50,y=160,width=96,height=30)
        self.GButton_112["command"] = self.GButton_112_command

        self.GButton_706=tk.Button(self.frame_main)
        self.GButton_706["bg"] = "#efefef"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_706["font"] = ft
        self.GButton_706["fg"] = "#000000"
        self.GButton_706["justify"] = "center"
        self.GButton_706["text"] = "加入关注"
        self.GButton_706.place(x=170,y=160,width=98,height=30)
        self.GButton_706["command"] = self.GButton_706_command



        self.GLineEdit_945=tk.Entry(self.frame_main)
        self.GLineEdit_945["borderwidth"] = "1px"
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_945["font"] = ft
        self.GLineEdit_945["fg"] = "#333333"
        self.GLineEdit_945["justify"] = "center"
        self.GLineEdit_945["text"] = "id"
        self.GLineEdit_945.place(x=40,y=120,width=253,height=30)

        self.GLabel_608=tk.Label(self.frame_main)
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_608["font"] = ft
        self.GLabel_608["fg"] = "#333333"
        self.GLabel_608["justify"] = "center"
        self.GLabel_608["text"] = "房间ID"
        self.GLabel_608.place(x=0,y=120,width=41,height=30)

        self.GLabel_538=tk.Label(self.frame_main)
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_538["font"] = ft
        self.GLabel_538["fg"] = "#333333"
        self.GLabel_538["justify"] = "center"
        self.GLabel_538["text"] = "主播名"
        self.GLabel_538.place(x=0,y=200,width=40,height=32)

        self.GLabel_803=tk.Label(self.frame_main)
        self.GLabel_803["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_803["font"] = ft
        self.GLabel_803["fg"] = "#333333"
        self.GLabel_803["justify"] = "center"
        self.GLabel_803.place(x=40,y=200,width=252,height=31)

        self.GLabel_953=tk.Label(self.frame_main)
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_953["font"] = ft
        self.GLabel_953["fg"] = "#333333"
        self.GLabel_953["justify"] = "center"
        self.GLabel_953["text"] = "房间名"
        self.GLabel_953.place(x=0,y=240,width=42,height=30)

        self.GLabel_201=tk.Label(self.frame_main)
        self.GLabel_201["bg"] = "#ffffff"
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_201["font"] = ft
        self.GLabel_201["fg"] = "#333333"
        self.GLabel_201["justify"] = "center"
        self.GLabel_201.place(x=40,y=240,width=253,height=30)

        self.GLabel_913=tk.Label(self.frame_main)
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_913["font"] = ft
        self.GLabel_913["fg"] = "#333333"
        self.GLabel_913["justify"] = "center"
        self.GLabel_913["text"] = "清晰度"
        self.GLabel_913.place(x=0,y=280,width=36,height=30)

        self.GLineEdit_440=ttk.Combobox(self.frame_main, state='readonly')
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_440["font"] = ft
        self.GLineEdit_440.place(x=40,y=280,width=254,height=30)
        self.GLineEdit_440.bind("<<ComboboxSelected>>", self.chooseCDN)

        self.GLabel_708=tk.Label(self.frame_main)
        ft = tkFont.Font(family='Times',size=10)
        self.GLabel_708["font"] = ft
        self.GLabel_708["fg"] = "#333333"
        self.GLabel_708["justify"] = "center"
        self.GLabel_708["text"] = "地址"
        self.GLabel_708.place(x=0,y=320,width=35,height=30)

        self.GLineEdit_795=tk.Entry(self.frame_main)
        self.GLineEdit_795["borderwidth"] = "1px"
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_795["font"] = ft
        self.GLineEdit_795["fg"] = "#333333"
        self.GLineEdit_795["justify"] = "center"
        self.GLineEdit_795["text"] = "address"
        self.GLineEdit_795.place(x=40,y=320,width=253,height=30)

        self.GLineEdit_136=tk.Entry(self.frame_main)
        self.GLineEdit_136["borderwidth"] = "1px"
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_136["font"] = ft
        self.GLineEdit_136["fg"] = "#333333"
        self.GLineEdit_136["justify"] = "center"
        self.GLineEdit_136["text"] = "关注列表"
        self.GLineEdit_136.place(x=300,y=0,width=293,height=352)
        yscroll = Scrollbar(self.GLineEdit_136, orient=VERTICAL)
        yscroll.pack(side=RIGHT, fill=Y)
        titles = ('房号', '主播', '操作')
        self.tvList =ttk.Treeview(self.GLineEdit_136, columns=titles, style='Treeview', show='headings', height=21,
                                        yscrollcommand=yscroll.set)
        self.tvList.pack()
        for i in range(len(titles)):
            self.tvList.heading(column=titles[i], text=titles[i], anchor=CENTER) # 定义表头
            self.tvList.column(titles[i], minwidth=20, anchor=CENTER ,stretch=True) # 定义列
        self.tvList.column(titles[0], width=80, anchor=CENTER)
        self.tvList.column(titles[1], width=120, anchor='w')
        self.tvList.column(titles[2], width=75, anchor=CENTER)
        yscroll.config(command=self.tvList.yview)
        self.tvList.bind("<ButtonRelease-1>", self.tvList_leftButtonRelease)

    def tvList_leftButtonRelease(self,event):
        if str(event.widget) == ".!frame.!entry3.!treeview":  # 左键释放的是否为表格
            items = event.widget.selection()
            try:
                item = self.tvList.item(items[0])['values']
                id = item[0]
                name = item[1]
                self.GLineEdit_945.delete(0,'end')
                self.GLineEdit_945.insert(0,id)
                self.GLabel_803['text'] = name
                self.GButton_112_command()
            except:
                pass
            row = self.tvList.identify_row(event.y)  # 点击的行
            column = self.tvList.identify_column(event.x)  # 点击的列
            col = int(str(column).replace('#', ''))  # 列号
            item = self.tvList.item(row)['values']
            if item:
                if col == 3:
                    # print("删除操作")
                    value = f'{item[0]}={item[1]}'
                    self.zhubo_list.remove(value)
                    self.tvList.delete(row)
                    self.save_list(self.zhubo_list)
    def save_list(self,zhubo_list):
         with open('HYZBconfig.ini', 'w', encoding='utf-8') as writer:
            for item in zhubo_list:
                writer.writelines(item)
                writer.writelines('\n')

    def getzhubolist(self):
        try:
            file = open("HYZBconfig.ini", "rb")
            l1 = []
            while 1:
                line = file.readline().strip()
                data = line.decode('utf-8', 'ignore') #ignore"的作用就是有异常就越过
                if len(data)>0 and len(data.split('='))>1 :
                    l1.append(data)
                if not line:
                    break
            return l1
        except:
            with open('HYZBconfig.ini', 'w', encoding='utf-8') as writer:
                writer.writelines('关注列表')
                writer.writelines('\n')
            return []

    #关注
    def GButton_706_command(self):
        roomid = self.GLineEdit_945.get().strip()
        anchor = self.GLabel_803.cget("text")
        self.tvList.insert('','end',values=((roomid,anchor,'删除')))
        self.zhubo_list.append((f'{roomid}={anchor}'))
        with open('HYZBconfig.ini', 'a+', encoding='utf-8') as writer:
            writer.writelines(f'{roomid}={anchor}')
            writer.writelines('\n')

    def settvlist(self,zhubo_list):
        if len(zhubo_list) < 1:
            return
        for zhubo in zhubo_list:
            self.count +=1
            li = zhubo.split('=')
            li.append('删除')
            self.tvList.insert('','end',values=(li))

    def GButton_274_command(self):
        url = self.GLineEdit_795.get().strip()
        if not url:
            return
        if self.player.get_state() == 0:
            self.player.resume()
        elif self.player.get_state() == 1:
            self.player.play(url)
        else:
            self.player.play(url)
        self.frame_video.tkraise()
    #停止
    def GButton_159_command(self):
        self.player.stop()
        self.frame_main.tkraise()
    #暂停
    def GButton_751_command(self):
        self.player.pause()
    #静音
    def GButton_991_command(self):
        vol = self.player.get_volume()
        if vol == 0:
            self.player.set_volume(self.vol)
        else:
            self.vol = self.player.get_volume()
            self.player.set_volume(0)
    #调音
    def GButton_79_command(self,value):
        self.player.set_volume(int(value))
        # self.scint

    #全屏
    def GButton_39_command(self):
        if  self.flag:
            self.root.attributes('-fullscreen',True)
            # self.frame_video.tkraise()
            self.frame_buttom.grid_forget()
        else:
            self.root.attributes('-fullscreen',False)
            self.frame_buttom.grid(row=1,column=0,sticky=NSEW,padx=0, pady=0 )
        self.flag = not self.flag

    def change_vol(self,evt):
        vol = self.player.get_volume()
        if evt.delta == 120:
            if vol < 100:
                vol += 5
        else:
            if vol > 0:
                vol -= 5
        self.player.set_volume(vol)
        self.scint.set(vol)
        print(vol)





    def changescreen(self,event):
        self.GButton_39_command()
    def exitfullscreen(self,event):
        self.flag = True
        self.root.attributes('-fullscreen',False)
        self.frame_buttom.grid(row=1,column=0,sticky=NSEW,padx=0, pady=0 )

    def create_video_view(self,wid):
        self.player.set_window(wid)

    def choose_active(self,event):
        url = 'https://www.huya.com/'
        text = self.GLineEdit_678.get()
        url += text.split('/')[1]
        self.set_game_list(url)
    def set_game_list(self,url):
        # url = 'https://www.huya.com/g'
        req = requests.get(url, headers=self.headers).content.decode('utf8', 'ignore')
        html_etree = etree.HTML(req)
        game_list =  html_etree.xpath('//*[@id="js-game-list"]/li')
        value =[]
        for idx,row in enumerate(game_list):
            idx +=1
            game = row.attrib['title']
            url =  self.get_row_text(row,'./a','href')
            value.append((game,url))
        self.GLineEdit_803["values"] = value
        self.GLineEdit_803.current(0)
        self.choose_game(None)
    def choose_game(self,event):
        url = 'http'
        text = self.GLineEdit_803.get()
        url += text.split('http')[1]
        self.set_live_list(url)
    def set_live_list(self,url):
        req = requests.get(url, headers=self.headers).content.decode('utf8', 'ignore')
        html_etree = etree.HTML(req)
        live_list =  html_etree.xpath('//*[@id="js-live-list"]/li')
        value =[]
        for idx,row in enumerate(live_list):
            idx +=1
            nick =   self.get_row_text(row,'.//*[@class="nick"]')
            title =   self.get_row_text(row,'.//*[@class="title"]')
            #人气
            js_num = self.get_row_text(row,'.//i[@class="js-num"]')
            tag_recommend =  self.get_row_text(row,'.//*[@class="tag tag-recommend"]')
            #英雄
            pos2_content =   self.get_row_text(row,'.//*[@class="tag-pos2-content"]')
            url_anchor =  self.get_row_text(row,'.//a','href')
            value.append((nick,title,js_num,tag_recommend,pos2_content,url_anchor))
        self.GLineEdit_178["values"] = value
        self.GLineEdit_178.current(0)
        self.choose_anchor(None)

    def choose_anchor(self,event):
        url = 'http'
        text = self.GLineEdit_178.get()
        url += text.split('http')[1]
        req = requests.get(url, headers=self.headers).content.decode('utf8', 'ignore')
        html_etree = etree.HTML(req)
        host_rid =  self.get_row_text(html_etree,'//span[@class="host-rid"]/em')
        self.GLineEdit_945.delete(0,'end')
        self.GLineEdit_945.insert(0,host_rid)

    def get_row_text(self,str_html,str_analysis,str_attrib='0'):
        table_element = str_html.xpath(str_analysis)
        if len(table_element) > 0:
            if str_attrib == '0':
                return table_element[0].text
            else:
                return table_element[0].attrib[str_attrib]
        else:
            return ' '

    #解析
    def GButton_112_command(self):
        self.GLineEdit_795.delete(0,'end')
        room_id = self.GLineEdit_945.get().strip()
        if not room_id:
            return
        try:
            api_url = 'https://mp.huya.com/cache.php?m=Live&do=profileRoom&roomid='
            html = requests.get(api_url + room_id, headers=self.headers)
            data = json.loads(html.text)['data']
            nick = data['profileInfo']['nick']
            room_name = data['liveData']['roomName']
            liveStatus = data['liveStatus']
        except:
            self.GLabel_803['text']='房号错误!'
            return
        if liveStatus == "OFF":
            self.GLabel_803['text']=f'未开播 {nick}'
            return f'{room_name} {nick} is offline'
        elif liveStatus == "REPLAY":
            self.GLabel_803['text']=f'未开播 {nick}'
            return f'{room_name} {nick} is REPLAY'
        else:
            self.GLabel_803['text']=f'{nick}'
            self.GLabel_201['text']=f'{room_name}'
            stream_dict = data['stream']
            flv = stream_dict['flv']  # type: dict
            cdn = flv['multiLine']  # type: List
            bitRateInfo = json.loads(data['liveData']['bitRateInfo'])
            bitRateInfo.append(({'sDisplayName': '原画', 'iBitRate': -1, 'iCodecType': 0, 'iCompatibleFlag': 0, 'iHEVCBitRate': -1}))
            listbox = []
            for item in bitRateInfo:
                count=0
                for i in cdn:
                    count += 1
                    url = i['url'].replace('http://', 'https://')
                    if item["iBitRate"] >= 0:
                      url = url.replace('imgplus.flv', f'imgplus_{item["iBitRate"]}.flv')
                    listbox.append(f'【{item["sDisplayName"]}-线路{count}】::{url}')

        self.GLineEdit_440["values"] = listbox
        for i in listbox:
            if i.startswith('【蓝光4M】'):
                # self.GListBox_294.current(1)
                self.GLineEdit_440.set(i)
                self.GLineEdit_795.delete(0,'end')
                self.GLineEdit_795.insert(0,i.split('::')[1])
                break
        else:
            self.GLineEdit_440.current(1)
            self.GLineEdit_795.delete(0,'end')
            self.GLineEdit_795.insert(0,i.split('::')[1])

    def chooseCDN(self,event):
        url = self.GLineEdit_440.get()
        self.GLineEdit_795.delete(0,'end')
        self.GLineEdit_795.insert(0,url.split('::')[1])

if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    root.mainloop()


免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
kololi + 1 + 1 更新很棒

查看全部评分

推荐
simgo2231 发表于 2024-2-6 10:18
大佬 出现了这个问题 能帮忙看看、?
Traceback (most recent call last):
  File "huya_live_read2.py", line 677, in <module>
  File "huya_live_read2.py", line 140, in __init__
  File "huya_live_read2.py", line 557, in choose_active
  File "huya_live_read2.py", line 571, in set_game_list
  File "huya_live_read2.py", line 576, in choose_game
  File "huya_live_read2.py", line 591, in set_live_list
  File "huya_live_read2.py", line 613, in get_row_text
  File "src\lxml\etree.pyx", line 2494, in lxml.etree._Attrib.__getitem__
KeyError: 'href'
沙发
青春小韭菜 发表于 2022-10-16 23:48
3#
花葬 发表于 2022-10-16 23:50
刚刚去测试了下,显示房间号错误。不知道我是不是个例。
当然,我输入的是房间号
4#
zdmboot 发表于 2022-10-17 02:11
好东西,值得点赞......
5#
feng_129 发表于 2022-10-17 02:30
流畅,清晰度不错。要是有自定义缩放就更好了~
6#
candleliu 发表于 2022-10-17 06:10
支持原创,膜拜的大佬
7#
我还行 发表于 2022-10-17 07:21
感觉不错 下来试试看 感谢分享
8#
lx0720 发表于 2022-10-17 07:21
要是有自定义缩放就更好了~
9#
l441669899 发表于 2022-10-17 08:06
感谢楼主分享!
10#
duanxiaopeng 发表于 2022-10-17 08:33
厉害,感谢楼主分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-24 13:53

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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