管道PyQt Widget图像到ffmpeg

时间:2014-10-30 02:17:35

标签: python ffmpeg pyqt

我有一个PyQt窗口,其窗口小部件会发生变化。我想制作一个视频。我发现this Answere非常有用,但似乎不可能在QtGui.QPixmap的save-method中使用子进程PIPE作为目标。我觉得我应该使用本机QtProcess进行这种工作,但我不知道如何PIPE图像,我看不到错误,因为我也看不到标准的outpur /错误。我想做的是这样的事情:

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_()

1 个答案:

答案 0 :(得分:2)

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

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_()