【问题标题】:PyQt-thread. Get dynamically outputPyQt 线程。获取动态输出
【发布时间】:2023-03-21 05:25:01
【问题描述】:

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

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 输出的示例:

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=...”开始)以计算总体进度?

【问题讨论】:

    标签: python ffmpeg pyqt pyqt5 qthread


    【解决方案1】:

    您不必使用subprocess.check_output() + QThread,因为如您所见,您仅在执行完成时才获得日志。相反,请使用 QProcess 在转换仍在运行时通知日志。

    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'}
    

    【讨论】:

      猜你喜欢
      • 2010-09-26
      • 2014-11-01
      • 2018-01-15
      • 2014-06-16
      • 1970-01-01
      • 2020-03-23
      • 1970-01-01
      • 2016-11-16
      • 2021-11-28
      相关资源
      最近更新 更多