pyqt+vlc 播放rtsp/rtmp地址并嵌入任意frame中

先上效果图:

 代码:

import os, platform

# 设置VLC库路径,需在import vlc之前
os.environ['PYTHON_VLC_MODULE_PATH'] = "./VLC"

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)



import tkinter as tk


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.player = Player()#"--audio-visual=visual","--effect-list=scope", "--effect-fft-window=flattop"
        self.title("流媒体播放器")
        # self.create_video_view()
        # self.create_control_view()
        self._canvas = tk.Canvas(self, bg="black")
        self._canvas.pack()
        self.player.set_window(self._canvas.winfo_id())
        self.player.play("rtmp://192.168.1.3:1935/rtmp/test")

    def create_video_view(self):
        self._canvas = tk.Canvas(self, bg="black")
        self._canvas.pack()
        self.player.set_window(self._canvas.winfo_id())

    # def create_control_view(self):
    #     frame = tk.Frame(self)
    #     tk.Button(frame, text="播放", command=lambda: self.click(0)).pack(side=tk.LEFT, padx=5)
    #     tk.Button(frame, text="暂停", command=lambda: self.click(1)).pack(side=tk.LEFT)
    #     tk.Button(frame, text="停止", command=lambda: self.click(2)).pack(side=tk.LEFT, padx=5)
    #     frame.pack()

    # def click(self, action):
    #     if action == 0:
    #         if self.player.get_state() == 0:
    #             self.player.resume()
    #         elif self.player.get_state() == 1:
    #             pass  # 播放新资源
    #         else:
    #             self.player.play("rtmp://192.168.1.3:1935/rtmp/test")
    #     elif action == 1:
    #         if self.player.get_state() == 1:
    #             self.player.pause()
    #     else:
    #         self.player.stop()


import sys,win32gui
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPainter, QColor, QFont
from PyQt5 import QtCore

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(776, 519)
        self.frame = QFrame(Form)
        self.frame.setGeometry(QtCore.QRect(50, 30, 200, 200))
        self.frame.setStyleSheet("background-color: rgb(85, 255, 255);")
        self.frame.setFrameShape(QFrame.StyledPanel)
        self.frame.setFrameShadow(QFrame.Raised)
        self.frame.setObjectName("frame")
        self.frame_2 = QFrame(Form)
        self.frame_2.setGeometry(QtCore.QRect(60, 280, 221, 141))
        self.frame_2.setStyleSheet("background-color: rgb(85, 170, 255);")
        self.frame_2.setFrameShape(QFrame.StyledPanel)
        self.frame_2.setFrameShadow(QFrame.Raised)
        self.frame_2.setObjectName("frame_2")
        self.frame_3 = QFrame(Form)
        self.frame_3.setGeometry(QtCore.QRect(410, 310, 241, 151))
        self.frame_3.setStyleSheet("background-color: rgb(255, 170, 255);")
        self.frame_3.setFrameShape(QFrame.StyledPanel)
        self.frame_3.setFrameShadow(QFrame.Raised)
        self.frame_3.setObjectName("frame_3")

        self.pushButton_area_show = QPushButton(Form)
        self.pushButton_area_show.setText("123")
        self.pushButton_area_show.clicked.connect(self.test)

        self.pushButton_area_show = QPushButton(Form)
        self.pushButton_area_show.setText("456")
        self.pushButton_area_show.setGeometry(QtCore.QRect(70, 270, 100, 100))
        self.pushButton_area_show.clicked.connect(self.test2)

        self.player = Player("--network-caching=0")#"--audio-visual=visual","--effect-list=scope", "--effect-fft-window=flattop"
        self.player.set_window(self.frame.winId())
        # self.player.play("rtmp://192.168.1.3:1935/rtmp/test")
        # self.player.play("rtmp://192.168.1.5:1935/live/test3")
        # self.player.play("rtsp://admin:castle12345@192.168.1.120:554/LiveMedia/ch1/Media1")
        self.player.play("rtsp://admin:hik12345@192.168.1.64:554/h264/ch01/sub/av_stream")

        # calc_hwnd = win32gui.FindWindow(None, u"rtmp://192.168.1.3:1935/rtmp/test")
        # print(calc_hwnd)
        # _h = self.frame.winId()
        # print(_h)
        # win32gui.SetParent(calc_hwnd, _h)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))

    def test(self):
        print(1)
        self.player.stop()

    def test2(self):
        print(2)
        self.player.play("rtmp://192.168.1.3:1935/rtmp/test")
        
        
class App2(QWidget,Ui_Form):
    def __init__(self):
        super(App2,self).__init__()
        self.setupUi(self)

if "__main__" == __name__:
    # app = App()
    # app.mainloop()
    app = QApplication(sys.argv)
    ex = App2()
    ex.show()
    sys.exit(app.exec_())

  代码说明:

# 设置VLC库路径,需在import vlc之前
os.environ['PYTHON_VLC_MODULE_PATH'] = "./VLC"

这段代码是引入VLC,在项目当前目录下放入VLC

 VLC下载地址:https://www.videolan.org/

可删除部分不必要文件减少项目体积

import vlc

安装python-vlc

#这个要先安装python-vlc
pip install python-vlc

Player是封装的播放器类直接引用

import tkinter as tk
......

这段代码是给使用tkinter开发

最后是

PyQt5

安装教程可参考:https://www.cnblogs.com/wohuiyijiu/p/12454130.html

重要的三行代码(其余都是绘制控件,不做说明):

self.player = Player("--network-caching=0")#"--audio-visual=visual","--effect-list=scope", "--effect-fft-window=flattop"
self.player.set_window(self.frame.winId())
# self.player.play("rtmp://192.168.1.3:1935/rtmp/test")
# self.player.play("rtmp://192.168.1.5:1935/live/test3")
# self.player.play("rtsp://admin:castle12345@192.168.1.120:554/LiveMedia/ch1/Media1")
self.player.play("rtsp://admin:hik12345@192.168.1.64:554/h264/ch01/sub/av_stream")

初始化播放器->设置句柄(设置在哪个frame播放,这里也不一定是frame,只要控件支持获取句柄应该都能播放)->传入播放地址播放

代码没有整理(界面和操作分离),有很多注释部分也有参考价值,告辞!

原文地址:https://www.cnblogs.com/wohuiyijiu/p/12840934.html