use one version of ffmpeg for all tasks, remove avconv dependency, fixes #2606

This commit is contained in:
j 2015-01-05 16:07:55 +00:00
commit e1bc418e0c
6 changed files with 61 additions and 161 deletions

View file

@ -16,7 +16,7 @@ from django.contrib.auth.models import User
import ox.jsonc
from ox.utils import json
from archive.extract import supported_formats, AVCONV, avconv_version
from archive.extract import supported_formats
from item.utils import get_by_id
@ -126,25 +126,24 @@ def load_config():
if f not in sformats or not sformats[f]:
sys.stderr.write('''WARNING:
Your configuration contains a video format "%s" that is
not supported by your version of avconv. Make sure you
dont have a local version of avconv in /usr/local/bin
and libavcodec-extra-53 and libav-tools are installed:
sudo apt-get install libavcodec-extra-53 libav-tools
not supported by your version of ffmpeg. Make sure you
dont have a local version of ffmpeg in /usr/local/bin
and ffmpeg is installed from ppa:j/pandora:
sudo add-apt-repository ppa:j/pandora
sudo apt-get install ffmpeg
''' % f)
else:
sys.stderr.write('''WARNING:
You dont have "%s" installed.
To fix this on Ubuntu 12.04, run:
You dont have "ffmpeg" installed. To fix this on Ubuntu 14.04, run:
sudo apt-get install libavcodec-extra-53 libav-tools
sudo add-apt-repository ppa:j/pandora
sudo apt-get install ffmpeg
check the README for further details.
''' % AVCONV)
''')
settings.AVCONV_VERSION = avconv_version()
settings.CONFIG = config
admin = len(settings.CONFIG['userLevels']) - 1
if not 'syncdb' in sys.argv \

View file

@ -11,6 +11,7 @@ import tempfile
import time
import math
import shutil
from distutils.spawn import find_executable
from glob import glob
import numpy as np
@ -22,8 +23,6 @@ from django.conf import settings
img_extension='jpg'
AVCONV = 'avconv'
MAX_DISTANCE = math.sqrt(3 * pow(255, 2))
@ -50,32 +49,18 @@ class AspectRatio(fractions.Fraction):
return "%d:%d" % (self.numerator, self.denominator)
def supported_formats():
p = subprocess.Popen(['which', AVCONV],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
stdout, stderr = p.communicate()
if not stdout.strip():
if not find_executable(settings.FFMPEG):
return None
p = subprocess.Popen([AVCONV, '-codecs'],
p = subprocess.Popen([settings.FFMPEG, '-codecs'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
stdout, stderr = p.communicate()
return {
'ogg': 'libtheora' in stdout and 'libvorbis' in stdout,
'webm': 'libvpx' in stdout and 'libvorbis' in stdout,
'mp4': 'libx264' in stdout and 'libvo_aacenc' in stdout,
'mp4': 'libx264' in stdout and 'DEA.L. aac' in stdout,
}
def avconv_version():
p = subprocess.Popen([AVCONV],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
stdout, stderr = p.communicate()
version = stderr.split(' ')[2].split('-')[0]
try:
version = int(version.split('.')[0])
except:
pass
return version
def stream(video, target, profile, info, avconv=None, audio_track=0):
def stream(video, target, profile, info, audio_track=0):
if not os.path.exists(target):
ox.makedirs(os.path.dirname(target))
@ -189,55 +174,13 @@ def stream(video, target, profile, info, avconv=None, audio_track=0):
'-auto-alt-ref', '1',
]
if format == 'mp4':
#quicktime does not support bpyramid
'''
video_settings += [
'-vcodec', 'libx264',
'-flags', '+loop+mv4',
'-cmp', '256',
'-partitions', '+parti4x4+parti8x8+partp4x4+partp8x8+partb8x8',
'-me_method', 'hex',
'-subq', '7',
'-trellis', '1',
'-refs', '5',
'-bf', '3',
'-flags2', '+bpyramid+wpred+mixed_refs+dct8x8',
'-coder', '1',
'-me_range', '16',
'-keyint_min', '25', #FIXME: should this be related to fps?
'-sc_threshold','40',
'-i_qfactor', '0.71',
'-qmin', '10', '-qmax', '51',
'-qdiff', '4'
'-c:v', 'libx264',
'-preset:v', 'medium',
'-profile:v', 'baseline',
# does not work with avconv in Ubuntu 14.04 yet
#'-level', '3.0',
]
'''
if settings.AVCONV_VERSION >= 9:
video_settings += [
'-vcodec', 'libx264',
'-preset:v', 'medium',
'-profile:v', 'baseline',
# does not work with avconv in Ubuntu 14.04 yet
#'-level', '3.0',
]
else:
video_settings += [
'-vcodec', 'libx264',
'-flags', '+loop+mv4',
'-cmp', '256',
'-partitions', '+parti4x4+parti8x8+partp4x4+partp8x8+partb8x8',
'-me_method', 'hex',
'-subq', '7',
'-trellis', '1',
'-refs', '5',
'-bf', '0',
'-flags2', '+mixed_refs',
'-coder', '0',
'-me_range', '16',
'-sc_threshold', '40',
'-i_qfactor', '0.71',
'-qmin', '10', '-qmax', '51',
'-qdiff', '4'
]
video_settings += ['-map', '0:%s,0:0'%info['video'][0]['id']]
else:
video_settings = ['-vn']
@ -271,15 +214,13 @@ def stream(video, target, profile, info, avconv=None, audio_track=0):
if audiobitrate:
audio_settings += ['-ab', audiobitrate]
if format == 'mp4':
audio_settings += ['-acodec', 'libvo_aacenc']
audio_settings += ['-c:a', 'aac', '-strict', '-2']
else:
audio_settings += ['-acodec', 'libvorbis']
audio_settings += ['-c:a', 'libvorbis']
else:
audio_settings = ['-an']
if not avconv:
avconv = AVCONV
cmd = [avconv, '-y', '-i', video, '-threads', '4', '-map_metadata', '-1', '-sn'] \
cmd = [settings.FFMPEG, '-y', '-i', video, '-threads', '4', '-map_metadata', '-1', '-sn'] \
+ audio_settings \
+ video_settings
@ -355,52 +296,41 @@ def frame(video, frame, position, height=128, redo=False, info=None):
if redo or not exists(frame):
ox.makedirs(folder)
if video.endswith('.mp4'):
if settings.FFMPEG:
cmd = ffmpeg_frame_cmd(video, frame, position, height)
else:
cmd = avconv_frame_cmd(video, frame, position, height)
cmd = ffmpeg_frame_cmd(video, frame, position, height)
else:
cmd = ['oxframe', '-i', video, '-o', frame,
'-p', str(position), '-y', str(height)]
run_command(cmd)
def avconv_frame_cmd(video, frame, position, height=128):
cmd = [
AVCONV, '-y',
'-ss', str(position),
'-i', video,
'-an', '-vframes', '1',
'-vf', 'scale=-1:%s' % height
]
if not frame.endswith('.png'):
cmd += ['-f', 'mjpeg']
cmd += [frame]
return cmd
def ffmpeg_frame_cmd(video, frame, position, height=128):
cmd = [
settings.FFMPEG, '-y',
'-ss', str(position),
'-i', video,
'-an', '-frames:v', '1',
'-vf', 'scale=-1:%s' % height,
'-vf', 'scale=-1:%s' % height if height else 'scale=iw*sar:ih',
frame
]
return cmd
def ffmpeg_version():
p = subprocess.Popen([settings.FFMPEG],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
stdout, stderr = p.communicate()
version = stderr.split(' ')[2].split('-')[0]
try:
version = tuple(map(int, version.split('.')))
except:
pass
return version
def frame_direct(video, target, position):
fdir = os.path.dirname(target)
if fdir and not os.path.exists(fdir):
os.makedirs(fdir)
pre = position - 2
if pre < 0:
pre = 0
else:
position = 2
cmd = [ox.file.cmd('ffmpeg'), '-y', '-ss', str(pre), '-i', video, '-ss', str(position),
'-vf', 'scale=iw*sar:ih',
'-an', '-vframes', '1', target]
cmd = ffmpeg_frame_cmd(video, target, position, None)
r = run_command(cmd)
return r == 0
@ -595,13 +525,13 @@ def chop(video, start, end):
ext = os.path.splitext(video)[1]
choped_video = '%s/tmp%s' % (tmp, ext)
cmd = [
'ffmpeg',
settings.FFMPEG,
'-y',
'-i', video,
'-ss', '%.3f'%start,
'-t', '%.3f'%t,
'-vcodec', 'copy',
'-acodec', 'copy',
'-c:v', 'copy',
'-c:a', 'copy',
'-f', ext[1:],
choped_video
]

View file

@ -453,9 +453,6 @@ class File(models.Model):
if self.data and len(audio) > 1:
config = settings.CONFIG['video']
resolution = self.stream_resolution()
ffmpeg = ox.file.cmd('ffmpeg')
if ffmpeg == 'ffmpeg':
ffmpeg = None
tmp = tempfile.mkdtemp()
if not self.info.get('language'):
self.info['language'] = parse_language(audio[0].get('language'))
@ -471,8 +468,7 @@ class File(models.Model):
n += 1
profile = '%sp.%s' % (resolution, config['formats'][0])
target = os.path.join(tmp, language + '_' + profile)
ok, error = extract.stream(media, target, profile, info, ffmpeg,
audio_track=i+1)
ok, error = extract.stream(media, target, profile, info, audio_track=i+1)
if ok:
tinfo = ox.avinfo(target)
del tinfo['path']
@ -676,15 +672,12 @@ class Stream(models.Model):
def encode(self):
media = self.source.media.path if self.source else self.file.data.path
ffmpeg = ox.file.cmd('ffmpeg')
if self.source or ffmpeg == 'ffmpeg' or self.format != 'webm':
ffmpeg = None
if not self.media:
self.media.name = self.path(self.name())
target = self.media.path
info = ox.avinfo(media)
ok, error = extract.stream(media, target, self.name(), info, ffmpeg)
ok, error = extract.stream(media, target, self.name(), info)
# file could have been moved while encoding
# get current version from db and update
_self = Stream.objects.get(id=self.id)

View file

@ -152,8 +152,7 @@ LOGGING = {
AUTH_PROFILE_MODULE = 'user.UserProfile'
AUTH_CHECK_USERNAME = True
AVCONV_VERSION = 0
FFMPEG=False
FFMPEG='ffmpeg'
#=========================================================================
#Pan.do/ra related settings settings