fix ffmpeg

This commit is contained in:
iperov 2021-08-09 22:53:01 +04:00
parent 7aaa15340c
commit 3be99ce9f3
5 changed files with 73 additions and 31 deletions

View file

@ -1 +1 @@
from .ffmpeg import probe, run, run_play
from .ffmpeg import probe, run

View file

@ -1,8 +1,8 @@
import json
import subprocess
from typing import Union
def run(args, pipe_stdin=False, pipe_stdout=False, pipe_stderr=False, quiet_std_err=False):
def run(args, pipe_stdin=False, pipe_stdout=False, pipe_stderr=False, quiet_stderr=False) -> Union[subprocess.Popen,None]:
"""
run ffmpeg process
@ -10,11 +10,12 @@ def run(args, pipe_stdin=False, pipe_stdout=False, pipe_stderr=False, quiet_std_
otherwise None
"""
args = ['ffmpeg'] + args
stdin_stream = subprocess.PIPE if pipe_stdin else None
stdout_stream = subprocess.PIPE if pipe_stdout else None
stderr_stream = subprocess.PIPE if pipe_stderr else None
if quiet_std_err and not pipe_stderr:
if quiet_stderr and not pipe_stderr:
stderr_stream = subprocess.DEVNULL
try:
@ -53,20 +54,3 @@ def probe(filename):
raise Exception('ffprobe', out, err)
return json.loads(out.decode('utf-8'))
def run_play():
args = ['ffplay',
'-f', 'rawvideo',
'-pix_fmt', 'bgr24',
'-s', '256x144',
'-'
]
stdin_stream = subprocess.PIPE
stdout_stream = None
stderr_stream = None#subprocess.DEVNULL
try:
return subprocess.Popen(args, stdin=stdin_stream, stdout=stdout_stream, stderr=stderr_stream)
except Exception as e:
print('ffplay exception: ', e)
return None

View file

@ -0,0 +1,56 @@
import threading
import time
from io import IOBase
from typing import List
from collections import deque
class IOThreadLinesReader:
"""
continuously reads lines from IO in background thread.
"""
def __init__(self, io : IOBase, max_lines=None):
self._io = io
self._lock = threading.Lock()
self._lines = deque(maxlen=max_lines)
threading.Thread(target=self._proc, daemon=True).start()
def _proc(self):
io = self._io
lock = self._lock
lines = self._lines
while not io.closed and io.readable():
line = io.readline()
lock.acquire()
lines.append(line.decode('utf-8').rstrip())
lock.release()
if len(line) == 0:
break
time.sleep(0.01)
def get_lines(self, wait_new=True, till_eof=False) -> List[str]:
"""
"""
lock = self._lock
lines = self._lines
result = []
while True:
if len(lines) != 0:
lock.acquire()
result += lines
lines.clear()
lock.release()
if till_eof and len(result[-1]) != 0:
continue
return result
if not till_eof and not wait_new:
return None
time.sleep(0.001)

View file

@ -1 +1,2 @@
from .IO import FormattedMemoryViewIO, FormattedFileIO
from .IOThreadLinesReader import IOThreadLinesReader

View file

@ -3,10 +3,10 @@ from typing import Tuple
import numpy as np
from xlib import ffmpeg as lib_ffmpeg
from xlib import io as lib_io
from .FramePlayer import FramePlayer
class VideoFilePlayer(FramePlayer):
"""
Play video track from the video file using subprocess ffmpeg.
@ -125,22 +125,23 @@ class VideoFilePlayer(FramePlayer):
'-map', f'0:v:{self._stream_idx}',
'pipe:']
self._ffmpeg_proc = lib_ffmpeg.run (args, pipe_stdout=True, pipe_stderr=True)
return self._ffmpeg_proc is not None
self._ffmpeg_proc = ffmpeg_proc = lib_ffmpeg.run (args, pipe_stdout=True, pipe_stderr=True)
self._ffmpeg_proc_stderr_lines = None
if ffmpeg_proc is not None:
self._ffmpeg_proc_stderr_lines = lib_io.IOThreadLinesReader(ffmpeg_proc.stderr, max_lines=5)
return True
return False
def _ffmpeg_next_frame(self, frames_idx_offset=1):
frame_buffer = None
while frames_idx_offset != 0:
frame_buffer = self._ffmpeg_proc.stdout.read(self._ffmpeg_height*self._ffmpeg_width*3)
if len(frame_buffer) == 0:
err = self._ffmpeg_proc.stderr.read()
err_lines = err.decode('utf-8').split('\r\n')
err = '\r\n'.join(err_lines[-5:])
# End reached
# unpredicted end reached
err = '\r\n'.join(self._ffmpeg_proc_stderr_lines.get_lines(till_eof=True)[-5:])
self._ffmpeg_stop()
return None, err
frames_idx_offset -= 1