mediacms/files/backends.py

78 wiersze
2.0 KiB
Python

# ffmpeg only backend
import locale
import logging
import re
from subprocess import PIPE, Popen
logger = logging.getLogger(__name__)
class VideoEncodingError(Exception):
def __init__(self, *args, **kwargs):
self.message = args[0]
super(VideoEncodingError, self).__init__(*args, **kwargs)
RE_TIMECODE = re.compile(r"time=(\d+:\d+:\d+.\d+)")
console_encoding = locale.getdefaultlocale()[1] or "UTF-8"
class FFmpegBackend(object):
name = "FFmpeg"
def __init__(self):
pass
def _spawn(self, cmd):
try:
return Popen(
cmd,
shell=False,
stdin=PIPE,
stdout=PIPE,
stderr=PIPE,
close_fds=True,
)
except OSError as e:
raise VideoEncodingError("Error while running ffmpeg", e)
def _check_returncode(self, process):
ret = {}
stdout, stderr = process.communicate()
ret["code"] = process.returncode
return ret
def encode(self, cmd):
process = self._spawn(cmd)
buf = output = ""
while True:
out = process.stderr.read(10)
if not out:
break
try:
out = out.decode(console_encoding)
except UnicodeDecodeError:
out = ""
output = output[-500:] + out
buf = buf[-500:] + out
try:
line, buf = buf.split("\r", 1)
except BaseException:
continue
progress = RE_TIMECODE.findall(line)
if progress:
progress = progress[0]
yield progress
process_check = self._check_returncode(process)
if process_check["code"] != 0:
raise VideoEncodingError(output[-1000:]) # output could be huge
if not output:
raise VideoEncodingError("No output from FFmpeg.")
yield output[-1000:] # output could be huge