PyQt 线程。获取动态输出
PyQt-thread. Get dynamically output
我使用 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=..." 开始)以计算总体进度?
您不必使用 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:]):
#
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 线程通过 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=..." 开始)以计算总体进度?
您不必使用 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:]):
#
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'}