【问题标题】:Pipe PyQt Widget Images to ffmpeg管道 PyQt 小部件图像到 ffmpeg
【发布时间】:2014-12-25 23:02:33
【问题描述】:

我有一个 PyQt 窗口,其中的小部件会发生变化。我想把它拍成视频。我发现this Answere 非常有用,但是似乎不可能在 QtGui.QPixmap 的保存方法中使用子进程 PIPE 作为目标。我觉得我应该使用本机 QtProcess 来完成这种工作,但我不知道如何通过管道传输图像并且我看不到错误,因为我也看不到标准输出/错误。我想做的是这样的:

from PyQt4 import QtGui, QtCore
import random

app = QtGui.QApplication([])
win    = QtGui.QWidget()
layout = QtGui.QGridLayout()
win.setLayout(layout)

#picture frame
scene = QtGui.QGraphicsScene()
canvas  = QtGui.QGraphicsView(scene)
layout.addWidget(canvas,0,0)

# start button
def run():
    # set pen
    pen = QtGui.QPen(QtCore.Qt.red)
    size = canvas.size()

    # start seperate process
    process = QtCore.QProcess(app)
    process.start('ffmpeg',['-y', '-f', 'image2pipe', '-vcodec', 'mjpeg', '-r', '24',  '-i', '-', '-vcodec', 'mpeg4', '-qscale', '5', 'video.avi'])
    for i in range(100):
        x = random.randint(1, size.width()-1)
        y = random.randint(1, size.height()-1)        
        scene.addLine(x,y,x,y, pen=pen)
        QtGui.QPixmap.grabWidget(win).save(process, "jpeg")

but_run = QtGui.QPushButton("Go!")
but_run.clicked.connect(run)
layout.addWidget(but_run,1,0)

win.show()
app.exec_()

【问题讨论】:

    标签: python ffmpeg pyqt


    【解决方案1】:

    所以我自己想通了。只需添加几个命令:

    process.setProcessChannelMode(process.ForwardedChannels)会将子进程的错误和正常输出重定向到主进程。这使您可以查看 ffmpeg 做什么或不做什么。


    编辑:这实际上是不需要的。
    process.setOpenMode(process.WriteOnly)这将打开进程的输入通道。


    我将文件格式更改为 png,因为它看起来更好。 JPG 压缩不适用于大的单色区域。

    process.closeWriteChannel() 将关闭输入通道。这就是 ffmpeg 知道没有更多数据进入的方式。

    最后,调用process.terminate() 关闭进程。

    下面是功能齐全的代码:

    from PyQt4 import QtGui, QtCore
    import random
    
    app = QtGui.QApplication([])
    win    = QtGui.QWidget()
    layout = QtGui.QGridLayout()
    win.setLayout(layout)
    
    #picture frame
    scene = QtGui.QGraphicsScene()
    canvas  = QtGui.QGraphicsView(scene)
    layout.addWidget(canvas,0,0)
    
    # start button
    def run():
        # set pen
        pen = QtGui.QPen(QtCore.Qt.red)
        size = canvas.size()
    
        # start seperate process
        process = QtCore.QProcess(app)
        process.setProcessChannelMode(process.ForwardedChannels)
        #process.setOpenMode(process.WriteOnly)
        process.start('ffmpeg',['-y', '-vcodec', 'png', '-i', '-', '-vcodec', 'mpeg4', '-qscale', '5', '-r', '24', 'video.avi',"-loglevel", "debug"])
        for i in range(100):
            x = random.randint(1, size.width()-1)
            y = random.randint(1, size.height()-1)    
            scene.addLine(x,y,x,y, pen=pen)
            QtGui.QPixmap.grabWidget(win).save(process, "png")
        process.closeWriteChannel()
        process.terminate()
    but_run = QtGui.QPushButton("Go!")
    but_run.clicked.connect(run)
    layout.addWidget(but_run,1,0)
    
    win.show()
    app.exec_()
    

    【讨论】:

    • 您能注意一下 Qt5 现在需要什么吗?我将 QPixmap 行更改为 QtGui.QWidget.grab(win).save(process, "png"),但我没有看到 video.avi 被写入磁盘。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 2019-05-17
    • 2018-03-27
    • 2011-08-15
    • 2013-07-14
    • 2020-09-27
    • 2016-03-14
    相关资源
    最近更新 更多