[ACCEPTED]-Terminal text becomes invisible after terminating subprocess-subprocess

Accepted answer
Score: 22

Change the script so that proc.terminate() is not used. You 10 can stop an ffmpeg subprocess more politely with

  proc.send_signal(signal.SIGINT)
  proc.wait()

This 9 allows ffmpeg the chance to write whatever 8 escape sequences it needs to restore the 7 terminal.


edit: discovered later- another tip 6 to make ffmpeg behave better with Popen is to provide 5 it a subprocess.PIPE or open(os.devnull) in the stdin handle. Otherwise, it 4 seems to try to get input from the parent's 3 stdin which can cause weird terminal behaviour. A 2 running ffmpeg process is listening for 1 '?' and 'q' input on stdin.

Score: 8

As stated in this answer, ffmpeg expects data from 3 stdin. You can run ffmpeg with the -nostdin flag 2 and it will keep your terminal from hiding 1 keystrokes.

Score: 2

do you communicate with the subprocess? in 7 that case i would use pexpect which makes 6 that type of setup very simple, perhaps 5 you must wait for the command to finish? i.e.

 p = subprocess.Popen(argv, stdout=o, stderr=e)
 p.wait()
 if p.returncode != 0:
      print("problems")

that's 4 what i use on a dvd2h264 script i wrote 3 a while back, never had any problems with 2 it, but i don't redirect stdin/stderr to 1 tmpfiles..

Score: 2

os.system('stty sane') worked for me. It reset settings making 1 echo invisible.

Score: 1

10 years later, and just ran into the same 4 problem (Mac, Python 3.8.2).

Per this SO answer, I switched 3 to using Popen as a context manager, and 2 this ensured that ffmpeg was correctly releasing 1 any of its handles.

def raw_start_times(in_filename, silence_threshold, silence_duration, start_ms = 0, end_ms = 200 * 1000):
    """Given an in_filename, find possible split points (phrase start
    times) using ffmpeg.

    Note that potential phrase start times are actually when any
    silence in the clip *ends*.
    """

    timematch = r'(?P<deltafromstart>[0-9]+(\.?[0-9]*))'
    end_re = re.compile(f'silence_end: {timematch} ')

    # The time returned is the deltafromstart; i.e., the actual
    # time is the start_ms + the delta.
    def time_ms(m):
        return start_ms + round(float(m.group('deltafromstart')) * 1000)

    # ffmpeg outputs e.g. "silence_end: 123.234" to stderr.
    def add_if_matches_end_re(line, arr):
        s = line.decode('utf-8').strip()
        end_match = end_re.search(s)
        if end_match:
            arr.append(time_ms(end_match))

    ffmpegcmd = (
        ffmpeg
        .input(in_filename, ss=(start_ms/1000.0), t=(end_ms-start_ms)/1000.0)
        .filter('silencedetect', n='{}dB'.format(silence_threshold), d=silence_duration)
        .output('-', format='null')
        .compile()
    ) + ['-nostats']  # FIXME: use .nostats() once it's implemented in ffmpeg-python.
    logger.debug(f'Running command: {subprocess.list2cmdline(ffmpegcmd)}')

    chunk_starts = [start_ms]
    with subprocess.Popen(
            ffmpegcmd,
            stderr=subprocess.PIPE,
            stdout = subprocess.PIPE) as p:
        for line in p.stderr:
            add_if_matches_end_re(line, chunk_starts)
    return chunk_starts

Score: 0

How about:

 try:
     p = subprocess.Popen(argv, stdout=o, stderr=e)
 except KeyboardInterrupt:
     p.send_signal(signal.SIGINT)
     p.wait()

0

More Related questions