PyQt线程.动态输出 [英] PyQt-thread. Get dynamically output

查看:56
本文介绍了PyQt线程.动态输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用PyQt线程通过ffmpeg将mp3文件并行转换为aac.这是我的代码:

I use PyQt-thread for parallel conversion of mp3 files to aac via ffmpeg. Here is my code:

class SubprocessThread(QThread):
    signal = pyqtSignal('PyQt_PyObject')

    def __init__(self, command, args):
        QThread.__init__(self)
        self.command = command
        self.args = args

    def __del__(self):
        self.wait()

    def run(self):
        output = subprocess.check_output('{0} {1}'.format(self.command, self.args), shell=True).split()
        self.signal.emit(output)

这是用法示例:

threads = []

for part in parts.keys():
    args = "-i \'{0}.mp3\' -c:a aac -b:a {1}k \'{2}.m4a\'".format(
        os.path.join(tmp_dir, str(part)),
        int(self.bitrate_cbx.currentText()),
        os.path.join(tmp_dir, str(part)))
    print(args)  # debug
    ffmpeg_thread = SubprocessThread('ffmpeg', args)
    ffmpeg_thread.signal.connect(self.on_data_ready)
    threads.append(ffmpeg_thread)
    ffmpeg_thread.start()
    self.threads_count += 1

我想根据转换创建进度条,但是ffmpeg总是更新其输出中的最后一个字符串(转换正在进行中).这是文件转换时ffmpeg输出的示例:

I want to make progress bar, based on conversion, but ffmpeg always updates last string in his output (when conversion in progress). Here is an example of ffmpeg output while files are converting:

user@host$ ffmpeg -i '/home/user/001.mp3' -c:a aac -b:a 128k -vn '/home/user/test.m4a' 
ffmpeg version n4.2.1 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 9.2.0 (GCC)
  configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-nvdec --enable-nvenc --enable-omx --enable-shared --enable-version3
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
Input #0, mp3, from '/home/user/001.mp3':
  Metadata:
    encoder         : Lavf57.41.100
    title           : test
    artist          : test
    album_artist    : test
    album           : test
    composer        : test
    genre           : test
    date            : 2018
  Duration: 00:12:38.02, start: 0.025056, bitrate: 192 kb/s
    Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 192 kb/s
    Metadata:
      encoder         : Lavc57.48
    Stream #0:1: Video: mjpeg (Baseline), yuvj420p(pc, bt470bg/unknown/unknown), 500x500 [SAR 1:1 DAR 1:1], 90k tbr, 90k tbn, 90k tbc (attached pic)
    Metadata:
      comment         : Cover (front)
Stream mapping:
  Stream #0:0 -> #0:0 (mp3 (mp3float) -> aac (native))
Press [q] to stop, [?] for help
Output #0, ipod, to '/home/user/test.m4a':
  Metadata:
    date            : test
    title           : test
    artist          : test
    album_artist    : test
    album           : test
    composer        : test
    genre           : test
    encoder         : Lavf58.29.100
    Stream #0:0: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s
    Metadata:
      encoder         : Lavc58.54.100 aac
size=   12107kB time=00:12:38.01 bitrate= 130.8kbits/s speed=79.2x 

如何从并行QThreads接收此数据(字符串,从"size = ..."开始的字符串)以计算总体进度?

How can I receive this data (string, that begins from "size=...") from my parallel QThreads to calculate overall progress?

推荐答案

您不必使用 subprocess.check_output() + QThread ,因为您只能看到执行完成后获取日志.而是使用 QProcess 在转换仍在运行时通知日志.

You do not have to use subprocess.check_output() + QThread since as you see you only get the log when the execution is finished. Instead, use QProcess that notifies the log while the conversion is still running.

class Converter(QObject):
    dataChanged = pyqtSignal(object)

    def __init__(self, parent=None):
        super().__init__(parent)

        self._process = QProcess()

        self._process.setProcessChannelMode(QProcess.MergedChannels)
        self._process.readyReadStandardOutput.connect(self.on_readyReadStandardOutput)

        self._process.setProgram("ffmpeg")

    def convert(self, source, destination, bitrate):
        # remove if destination exist
        QFile.remove(destination)
        args = ["-i", source, "-c:a", "aac", "-b:a", bitrate, "-vn", destination]
        self._process.setArguments(args)
        self._process.start()

    @pyqtSlot()
    def on_readyReadStandardOutput(self):
        keys = ("size", "time", "bitrate", "speed")
        data = self._process.readAllStandardOutput()
        msg = data.data().decode()
        for line in msg.splitlines():
            line = line.replace(" ", "").replace("=", "")
            if all(key in line for key in keys):
                values = []
                for left, right in zip(keys[:-1], keys[1:]):
                    # https://stackoverflow.com/a/51456576/6622587
                    value = line[line.index(left) + len(left) : line.index(right)]
                    values.append(value)
                value = line[line.index(keys[-1]) + len(keys[-1]) :]
                values.append(value)
                d = dict(zip(keys, values))
                self.dataChanged.emit(d)

这是用法示例:

    # ...
    converters = []

    for part in parts.keys():
        converter = Converter()
        converter.dataChanged.connect(self.on_data_ready)
        converter.convert(
            "{}.mp3".format(part),
            "{}.m4a".format(part),
            "{}k".format(self.bitrate_cbx.currentText()),
        )
        converters.append(converter)
        # ...
# ...

@pyqtSlot(object)
def on_data_ready(self, data):
    print(data)

输出:

{'size': '256kB', 'time': '00:00:17.94', 'bitrate': '116.9kbits/s', 'speed': '35.9x'}
{'size': '512kB', 'time': '00:00:44.62', 'bitrate': '94.0kbits/s', 'speed': '44.6x'}
{'size': '1024kB', 'time': '00:01:11.21', 'bitrate': '117.8kbits/s', 'speed': '47.5x'}
{'size': '1280kB', 'time': '00:01:37.66', 'bitrate': '107.4kbits/s', 'speed': '48.8x'}
{'size': '1941kB', 'time': '00:02:02.46', 'bitrate': '129.8kbits/s', 'speed': '49.6x'}

这篇关于PyQt线程.动态输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆