【问题标题】:Python monitoring progress of HandbrakePython监控Handbrake的进度
【发布时间】:2016-06-20 15:05:28
【问题描述】:

所以我使用 handbrake 和 python 根据时间表对视频进行编码。我需要监控进度,因为我用它来估计编码时间。然后我可以将它安装到我的调度程序中。

我在从流程中获取 ETA 和完成百分比时遇到问题。这是我到目前为止所拥有的

profile = ["HandBrakeCLI","-i",input,"-o","output","-e","x264"]
cp = subprocess.Popen(profile, stderr=subprocess.PIPE, bufsize=1)
for line in iter(cp.stderr.readline, b''):

  # regex match for % complete and ETA
  matches = re.match( r'.*(\d+\.\d+)\s%.*ETA\s(\d+)h(\d+)m(\d+)s', line.decode('utf-8') )

  if matches:
    print( matches.group() )

  print(line),

cp.stderr.close()
cp.wait()

它不匹配,事实上我不完全确定发生了什么。当我运行我的脚本时,我看到了 ETA 和 % complete 打印输出

Encoding: task 1 of 1, 1.19 % (45.57 fps, avg 62.74 fps, ETA 00h08m01s)

我尝试过使用标准输出,但它也不起作用。

【问题讨论】:

  • 我很确定问题是 Handbrake CLI 不会在每次进程进行一点时输出新的附加行,而是修改现有行。尝试在for line in inter.. 之后立即打印该行,看看它实际上给了你什么。
  • 这不会在 for 循环退出后给我输出吗?那么该过程何时完成?我想在这个过程中得到信息。
  • 首先,你在迭代stderr,也许你需要迭代stdout。其次,我认为 cp.stderr.readline 会从子进程本身返回完整的行,而不是单个重复更新的行。我会在handbreak 进程完成后打印最后一行,看看它的外观。而且,正如我告诉你的,我会打印 for 循环中的每一行,以了解我实际收到的内容。
  • 迭代标准输出不会打印出编码信息。我不明白你的意思,你能举个例子吗?
  • 尝试删除第 5-13 行,而只输出 print(line),并告诉我它实际打印的时间和内容。

标签: python subprocess progress-bar handbrake


【解决方案1】:

你需要从标准输出读取,而不是标准错误。

profile = ["HandBrakeCLI","-i",input,"-o","output","-e","x264"]
cp = subprocess.Popen(profile, stderr=subprocess.PIPE, strout=subprocess.PIPE, bufsize=1)
for line in iter(cp.stdout.readline, b''):

  # regex match for % complete and ETA
  matches = re.match( r'.*(\d+\.\d+)\s%.*ETA\s(\d+)h(\d+)m(\d+)s', line.decode('utf-8') )

  if matches:
    print( matches.group() )

  print(line),

cp.stderr.close()
cp.stdout.close()
cp.wait()

使用进度包装器(使用 clint.textui.progress.Bar)并逐字节读取(对我有用):

profile = ["HandBrakeCLI","-i",input,"-o","output","-e","x264"]
cp = subprocess.Popen(profile, stderr=subprocess.PIPE, strout=subprocess.PIPE, close_fds=True)
bar = Bar(label="Encoding %s" % input, width=30, expected_size=10000, every=1)
bar.show(0)

line = ""
c = 0

while True:    
  nl = cp.stdout.read(1)
  if nl == '' and cp.poll() is not None:
     break  # Aborted, no characters available, process died.
  if nl == "\n":
     line = ""
  elif nl == "\r":
     # regex match for % complete and ETA, assuming the regex is ok.
     matches = re.match( r'.*(\d+\.\d+)\s%.*ETA\s(\d+)h(\d+)m(\d+)s', line.decode('utf-8') )

     if matches:
        print( matches.group() )
        # do something
     line = ""
  else:
     line += nl

error = cp.stderr.read()
success = "Encode done!" in error

没有测试代码,重写它以匹配线程初始帖子。

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    这里有好骨头。但是,我必须进行一些修改才能使其适用于 Python 3.7 和 PyQt5。 ui 行用于 PyQt5 QProgressBar 和 QLineEdit

    此代码已经过测试。我感谢大家的帮助。

    def hbConvertISOtoMP4():

    line = ""
    inFile = #place your input file here!
    oFile =  #place your output file here!
    
    ui.progressBar.setValue(0)
    profile = ["HandBrakeCLI", "-t", "1", "-i", inFile, "-o", oFile, "-e", "x264"]
    cp = Popen(profile, stderr=PIPE, stdout=PIPE, close_fds=True)
    
    ui.leProgress.setText('Loading data... Please Wait.')
    ui.centralwidget.repaint()
    
    while True:
        nl = cp.stdout.read(1)
    
        if nl == '' or cp.poll() is not None:
            break  # Aborted, no characters available, process died.
    
        elif nl.hex() == '0d' and len(line) > 30:
    
            # regex match for % complete and ETA, assuming the regex is ok.
            matches = re.match(r'.*(\d+\.\d+)\s%.*ETA\s(\d+)h(\d+)m(\d+)s\)', line)
    
            if matches:
                # do something here
                # I inserted this code for a PyQt5 Progress Bar UI
                ui.leProgress.setText(line)
                ui.centralwidget.repaint()
                pBar = matches.group().split(' ')
                ui.progressBar.setValue(int(float(pBar[5])))
    
            line = ""
        else:
            line += nl.decode('utf-8')
    
    error = cp.stderr.read()
    
    if 'Encode done!' in str(error):
        ui.progressBar.setValue(0)
        ui.leProgress.setText("Encode Done!")
    else:
        ui.leProgress.setText('Error during Endoding')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-21
      • 1970-01-01
      • 2011-11-01
      • 1970-01-01
      • 2014-06-11
      • 1970-01-01
      • 1970-01-01
      • 2011-08-20
      相关资源
      最近更新 更多