【问题标题】:Is there a way to run a subprocess that opens a window in the background in Python?有没有办法运行在 Python 中在后台打开一个窗口的子进程?
【发布时间】:2021-08-24 01:30:10
【问题描述】:

我正在尝试使用 subprocess 在 Python 中调用 ffplay。当调用ffplay 时,它会打开一个带有视频的窗口并将信息输出到控制台,直到窗口关闭。我想在视频继续播放(即不关闭窗口)的同时抓取输出并返回到 Python 脚本。

目前,我有:

# some code
subprocess.call(['ffplay', 'video.mp4'])
# some more code

如何更改此代码以保持窗口打开并将进程输出发送到后台以继续 Python 脚本?

提前致谢!

【问题讨论】:

  • 我有一个英语问题。在问题的上下文中,术语“抓取输出”是什么意思?
  • @SpencerCain,这是哪个操作系统?如果是 Windows,则额外暴露了 subprocess.Popen 参数,专门用于控制子进程是否在单独的窗口中运行。
  • @Rotem 我的意思是输入废品,或者在这种情况下摆脱。对于造成的混乱,我深表歉意。
  • @SpencerCain 我的第一个示例摆脱了 FFmpeg 的所有输出文本。控制台窗口仍然打开,但它与 Python 应用程序的控制台相同(我的 Python 应用程序是控制台应用程序)。您的意思是也摆脱控制台窗口吗?
  • @Rotem 实际上,我的意图是创建一个带有同步视频的视频切换器。我想结合多个电话录音的音乐会和其他东西,并能够在视图之间切换,但保持一致(希望是音板级别)的音频。控制台窗口(现在)将控制切换

标签: python ffmpeg subprocess ffplay


【解决方案1】:

编辑

试试这个,

p = subprocess.Popen(['ffplay', 'sample-mp4-file.mp4', '-autoexit'],
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     universal_newlines=True) # This flag converts carriage return chars to new lines

while p.poll() is None:          # While the process p is still running
    line = p.stderr.readline()
    print(line)

我的输出:

ffplay version 4.2.4-1ubuntu0.1 Copyright (c) 2003-2020 the FFmpeg developers

  built with gcc 9 (Ubuntu 9.3.0-10ubuntu2)

  configuration: --prefix=/usr --extra-version=1ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared

  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

  libavresample   4.  0.  0 /  4.  0.  0

  libswscale      5.  5.100 /  5.  5.100

  libswresample   3.  5.100 /  3.  5.100

  libpostproc    55.  5.100 / 55.  5.100

    nan    :  0.000 fd=   0 aq=    0KB vq=    0KB sq=    0B f=0/0   

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'sample-mp4-file.mp4':

  Metadata:

    major_brand     : isom

    minor_version   : 512

    compatible_brands: isomiso2avc1mp41

    creation_time   : 1970-01-01T00:00:00.000000Z

    encoder         : Lavf53.24.2

  Duration: 00:02:05.95, start: 0.000000, bitrate: 669 kb/s

    Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 320x240 [SAR 1:1 DAR 4:3], 282 kb/s, 15 fps, 15 tbr, 15360 tbn, 30 tbc (default)

    Metadata:

      creation_time   : 1970-01-01T00:00:00.000000Z

      handler_name    : VideoHandler

    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, 5.1, fltp, 383 kb/s (default)

    Metadata:

      creation_time   : 1970-01-01T00:00:00.000000Z

      handler_name    : SoundHandler

  -0.01 A-V: -0.034 fd=   0 aq=  137KB vq=   93KB sq=    0B f=0/0   

   0.04 A-V: -0.027 fd=   0 aq=  135KB vq=   93KB sq=    0B f=0/0   

   0.07 A-V: -0.024 fd=   0 aq=  137KB vq=   94KB sq=    0B f=0/0   

   0.11 A-V: -0.022 fd=   0 aq=  135KB vq=   94KB sq=    0B f=0/0   

   0.14 A-V: -0.020 fd=   0 aq=  136KB vq=   94KB sq=    0B f=0/0   

   0.18 A-V: -0.020 fd=   0 aq=  136KB vq=   94KB sq=    0B f=0/0   

   0.20 A-V: -0.027 fd=   0 aq=  137KB vq=   92KB sq=    0B f=0/0   

   0.24 A-V: -0.025 fd=   0 aq=  135KB vq=   92KB sq=    0B f=0/0   

   0.27 A-V: -0.023 fd=   0 aq=  136KB vq=   93KB sq=    0B f=0/0   

   0.31 A-V: -0.020 fd=   0 aq=  134KB vq=   93KB sq=    0B f=0/0   

   0.34 A-V: -0.020 fd=   0 aq=  137KB vq=   89KB sq=    0B f=0/0   

   0.37 A-V: -0.028 fd=   0 aq=  135KB vq=   89KB sq=    0B f=0/0   

   0.41 A-V: -0.025 fd=   0 aq=  136KB vq=   89KB sq=    0B f=0/0   

   0.44 A-V: -0.023 fd=   0 aq=  134KB vq=   89KB sq=    0B f=0/0   

   0.48 A-V: -0.020 fd=   0 aq=  135KB vq=   86KB sq=    0B f=0/0   

   0.51 A-V: -0.020 fd=   0 aq=  135KB vq=   86KB sq=    0B f=0/0   

   0.54 A-V: -0.028 fd=   0 aq=  137KB vq=   83KB sq=    0B f=0/0   

   0.57 A-V: -0.025 fd=   0 aq=  134KB vq=   83KB sq=    0B f=0/0   

   0.61 A-V: -0.023 fd=   0 aq=  137KB vq=   82KB sq=    0B f=0/0   

   0.64 A-V: -0.020 fd=   0 aq=  135KB vq=   82KB sq=    0B f=0/0   

   0.68 A-V: -0.020 fd=   0 aq=  138KB vq=   78KB sq=    0B f=0/0   

   0.70 A-V: -0.027 fd=   0 aq=  136KB vq=   78KB sq=    0B f=0/0   

   0.74 A-V: -0.025 fd=   0 aq=  138KB vq=   76KB sq=    0B f=0/0   

   0.77 A-V: -0.022 fd=   0 aq=  136KB vq=   76KB sq=    0B f=0/0   

   0.81 A-V: -0.020 fd=   0 aq=  139KB vq=   73KB sq=    0B f=0/0   

   0.84 A-V: -0.020 fd=   0 aq=  137KB vq=   73KB sq=    0B f=0/0   

   0.87 A-V: -0.027 fd=   0 aq=  138KB vq=   69KB sq=    0B f=0/0   

   0.90 A-V: -0.025 fd=   0 aq=  136KB vq=   69KB sq=    0B f=0/0   

   0.94 A-V: -0.023 fd=   0 aq=  138KB vq=   67KB sq=    0B f=0/0   

   0.97 A-V: -0.023 fd=   0 aq=  138KB vq=   67KB sq=    0B f=0/0   

   1.01 A-V: -0.020 fd=   0 aq=  139KB vq=   64KB sq=    0B f=0/0   

   1.03 A-V: -0.028 fd=   0 aq=  137KB vq=   64KB sq=    0B f=0/0   

   1.07 A-V: -0.025 fd=   0 aq=  138KB vq=   62KB sq=    0B f=0/0   

   1.10 A-V: -0.025 fd=   0 aq=  138KB vq=   62KB sq=    0B f=0/0   

   1.14 A-V: -0.023 fd=   0 aq=  140KB vq=   60KB sq=    0B f=0/0   

   1.17 A-V: -0.020 fd=   0 aq=  138KB vq=   60KB sq=    0B f=0/0   

   1.20 A-V: -0.028 fd=   0 aq=  139KB vq=   57KB sq=    0B f=0/0   

   1.23 A-V: -0.028 fd=   0 aq=  139KB vq=   57KB sq=    0B f=0/0   

   1.27 A-V: -0.025 fd=   0 aq=  140KB vq=   56KB sq=    0B f=0/0   

   1.30 A-V: -0.023 fd=   0 aq=  138KB vq=   56KB sq=    0B f=0/0   

   1.34 A-V: -0.020 fd=   0 aq=  139KB vq=   54KB sq=    0B f=0/0   

我想这就是你要找的。​​p>

【讨论】:

    【解决方案2】:

    我认为Popen 是您正在寻找的。​​p>

    这是一个代码示例:

    import subprocess
    import time
    
    process = subprocess.Popen(['ffplay', '-hide_banner', '-nostats', '-autoexit', 'video.mp4'])
    
    for i in range(10):
        time.sleep(1)
        print('Continue running ' + str(i))
    
    process.wait()
    

    subprocess.Popen打开一个新的子进程,子子进程在后台执行。
    Python 脚本在subprocess.Popen 之后继续运行。

    您可以等待子进程完成,或终止它(或让它运行)。


    抓取stdoutstderr 输出的示例(将FFplay 输出读入Python 的内存)。

    import subprocess
    import time
    
    process = subprocess.Popen(['ffplay', '-autoexit', '-t', '1', 'video.mp4'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    
    stdout, stderr = process.communicate()
    
    process.wait()
    
    print('stdout = ' + stdout.decode('utf-8'))
    print('stderr = ' + stderr.decode('utf-8'))
    

    在执行其他操作时“在飞行中”读取 FFplay 统计信息,需要一个线程。
    在 Windows 中,我们似乎需要从 stderr 逐字节读取。
    readline() 不起作用,因为 FFplay 输出行以 LF (\r) 字符结尾。

    这是一个代码示例:

    import subprocess
    import threading
    
    # Read from stderr pipe - "draining the stderr pipe"
    def drain_pipe(a_process):
        output_txt = b''
        while a_process.poll() is None:
            try:
                # Read one byte at a time, it's the only way it works in Windows, because lines ends with just \r.
                a_char = a_process.stderr.read(1)
                output_txt += a_char
                if a_char == b'\r':  # Look for line feed character.
                    print(output_txt.decode('utf-8'))
                    output_txt = b''
            except:
                break  # Exception may be raised because the pipe closes asynchronous
    
    process = subprocess.Popen(['ffplay', '-stats', '-autoexit', 'video.mp4'], stderr=subprocess.PIPE)
    
    stderr_thread = threading.Thread(target=drain_pipe, args=(process,))  # Create a thread for reading from stderr
    stderr_thread.start()  # Start thread
    
    # some more code...
    
    process.wait()
    stderr_thread.join()  # Join thread
    

    【讨论】:

    • "Scrape the output" 在此上下文中意味着将被调用程序的输出读取到调用程序的内存中。
    猜你喜欢
    • 2014-09-04
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 2011-07-22
    • 2020-11-27
    • 1970-01-01
    • 2019-09-05
    相关资源
    最近更新 更多