微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将可变视频呈现到PyQt小部件?

如何解决如何将可变视频呈现到PyQt小部件?

我正在使用PyQt使用python开发视频编辑应用程序。我希望能够从视频文件中制作“剪辑”,并能够将这些剪辑连接起来以呈现新视频。我已经将QMediaPlayer类与VideoSurface一起使用,以播放已实例化带有.mp4文件的QVideoWidget的视频,但是我想使用numpy数组(首选)或某些可变对象来播放视频。我浏览了一些开源视频编辑器(OpenShot,Vidcutter,Pitivi),但似乎找不到我需要的东西。许多人使用我不熟悉的C ++框架。

我使用多线程和for循环尝试通过使用QImage对象来破解解决方案,这意味着我逐帧循环浏览视频,提取每个帧的numpy数组表示形式并将其转换为QImage对象并调用repaint()。不幸的是,即使在新线程上调用函数,也无法以所需的速度进行渲染。这是受moviepy使用pygame渲染剪辑的方法启发的。我也浏览了PyQt文档,但是这些类似乎无法满足我的需求,或者我听不懂。图形用户界面编程对我来说是新的。

我知道fps不是问题,如果您使用更新的VideoFileCLip参数运行下面的代码,则视频将以原始帧速率的大约75%显示(无声音)。并且,如果没有多线程,窗口将“不响应”。我曾尝试将fps设置为30和60,但仍然不希望使用for-loop方法,因为其他任务将在其他地方执行,并且计算复杂度只会增加

这是一个简化的版本,可以揭示该问题:

import numpy as np                                                     
import sys
import time
from PyQt5.QtGui import QImage,QPainter
from PyQt5.QtWidgets import QApplication,QWidget
import threading
from moviepy.editor import VideoFileClip

class Demo(QWidget):
    def __init__(self):
        super().__init__()
        self.video = VideoFileClip(r'C:\Users\jklew\Videos\Music\Fractalia.MP4') # I am using a real video
        im_np = self.video.get_frame(0)
        self.image = QImage(im_np,im_np.shape[1],im_np.shape[0],QImage.Format_RGB888)
        self.stopEvent = threading.Event()
        self.thread = threading.Thread(target=self.display_clip,args=())
        self.thread.start()

    def paintEvent(self,event):
        painter = QPainter(self)
        painter.drawImage(self.rect(),self.image)

    def display_clip(self,fps=60):
        clip = self.video
        img = clip.get_frame(0) # returns numpy array of frame at time 0

        t0 = time.time()

        for t in np.arange(1.0 / fps,clip.duration-.001,1.0 / fps):
            
            img = clip.get_frame(t) # returns numpy array of frame at time t
            # print(img.shape)
            t1 = time.time()
            time.sleep(max(0,t - (t1-t0))) # loop at framerate specified
            self.imdisplay(img) #,screen)
    
    def imdisplay(self,img_array):
        # fill the widget with the image array
        # Todo: Qt widget
        self.image = QImage(img_array,img_array.shape[1],img_array.shape[0],QImage.Format_RGB888)
        self.repaint()

def main():
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

此问题还扩展到可变音频数据。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。