PyQt线程.动态输出 [英] PyQt-thread. Get dynamically output
问题描述
我使用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屋!