Added more filters and a setup file

This commit is contained in:
Mathias Koehler 2011-10-17 14:39:49 +02:00
parent d832d4da80
commit d12a628c3b
7 changed files with 247 additions and 19 deletions

View file

@ -1,3 +1,5 @@
# -*- coding: utf8 -*- # -*- coding: utf8 -*-
from ffmpegwrapper.ffmpeg import FFmpeg, Input, Output from .ffmpeg import FFmpeg, Input, Output
from .codec import VideoCodec, AudioCodec, NO_AUDIO, NO_VIDEO
from .filter import VideoFilter, AudioFilter

View file

@ -5,6 +5,10 @@ from itertools import chain
from .options import CombinedOptions from .options import CombinedOptions
NO_AUDIO = ['-an']
NO_VIDEO = ['-vn']
class Codec(CombinedOptions): class Codec(CombinedOptions):
def __init__(self, name, *args): def __init__(self, name, *args):
@ -14,11 +18,95 @@ class Codec(CombinedOptions):
class VideoCodec(Codec): class VideoCodec(Codec):
def bitrate(self, bitrate):
self.add_option('-b', str(bitrate))
return self
def frames(self, number):
self.add_option('-vframes', str(number))
return self
def fps(self, fps):
self.add_option('-r', str(fps))
return self
def size(self, x, y):
filter = "{x}x{y}".format(x, y)
self.add_option('-s', filter)
return self
def aspect(self, x, y):
filter = self._format_parameter(x, y)
self.add_option('-aspect', filter)
return self
def bitrate_tolerance(self, tolerance):
self.add_option('-bt', str(tolerance))
return self
def max_bitrate(self, rate):
self.add_option('-maxrate', str(rate))
return self
def min_bitrate(self, rate):
self.add_option('-minrate', str(rate))
return self
def buffer_size(self, size):
self.add_option('-bufsize', str(size))
return self
def pass_number(self, number):
self.add_option('-pass', str(number))
return self
def language(self, lang):
self.add_option('-vlang', str(lang))
return self
def same_quality(self):
self.add_option('-sameq', None)
return self
def preset(self, preset):
self.add_option('-vpre', str(preset))
return self
def __iter__(self): def __iter__(self):
return chain(['-vcodec', self.name], Codec.__iter__(self)) return chain(['-vcodec', self.name], Codec.__iter__(self))
class AudioCodec(Codec): class AudioCodec(Codec):
def frames(self, number):
self.add_option('-aframes', str(number))
return self
def frequence(self, freq):
self.add_option('-ar', str(freq))
return self
def bitrate(self, rate):
self.add_option('-ab', str(rate))
return self
def quality(self, number):
self.add_option('-aq', str(number))
return self
def channels(self, number):
self.add_option('-ac', str(number))
return self
def language(self, lang):
self.add_option('-alang', str(lang))
return self
def preset(self, preset):
self.add_option('-apre', str(preset))
return self
def __iter__(self): def __iter__(self):
return chain(['-acodec', self.name], Codec.__iter__(self)) return chain(['-acodec', self.name], Codec.__iter__(self))

View file

@ -8,7 +8,12 @@
:license: BSD, see LICENSE for more details. :license: BSD, see LICENSE for more details.
""" """
from subprocess import Popen, PIPE
import os
from fcntl import fcntl, F_SETFL, F_GETFL
from select import select
from subprocess import Popen, PIPE, STDOUT
from itertools import chain from itertools import chain
from .options import CombinedOptions, Options from .options import CombinedOptions, Options
@ -30,6 +35,10 @@ class Output(CombinedOptions):
self.file = file self.file = file
CombinedOptions.__init__(self, *args) CombinedOptions.__init__(self, *args)
def overwrite(self):
self.add_option('-y', None)
return self
def __iter__(self): def __iter__(self):
return chain(CombinedOptions.__iter__(self), [self.file]) return chain(CombinedOptions.__iter__(self), [self.file])
@ -41,8 +50,17 @@ class FFmpeg(CombinedOptions):
CombinedOptions.__init__(self, *args) CombinedOptions.__init__(self, *args)
def run(self): def run(self):
return Popen(self, executable=self.binary, stdin=PIPE, self.pipe = Popen(self, executable=self.binary,
stdout=PIPE, stderr=PIPE) stderr=PIPE)
fcntl(self.pipe.stderr.fileno(), F_SETFL,
fcntl(self.pipe.stderr.fileno(), F_GETFL) | os.O_NONBLOCK)
return self
def wait_for_data(self):
while True:
ready = select([self.pipe.stderr.fileno()], [], [])[0]
if ready:
return True
def add_option(self, key, value): def add_option(self, key, value):
self._list.insert(0, Options({key: value})) self._list.insert(0, Options({key: value}))

14
setup.py Normal file → Executable file
View file

@ -0,0 +1,14 @@
#!/usr/bin/env python
# -*- coding: utf8 -*-
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
setup(
name="ffmpegwrapper",
version="0.1-dev",
packages=['ffmpegwrapper']
)

120
test.py
View file

@ -2,9 +2,8 @@
import unittest import unittest
from ffmpegwrapper import FFmpeg, Input, Output from ffmpegwrapper import FFmpeg, Input, Output, \
from ffmpegwrapper.codec import VideoCodec, AudioCodec VideoCodec, AudioCodec, VideoFilter
from ffmpegwrapper.filter import VideoFilter
from ffmpegwrapper.options import Options from ffmpegwrapper.options import Options
@ -46,12 +45,11 @@ class FFmpegTestCase(unittest.TestCase):
def test_filter_interface(self): def test_filter_interface(self):
filter = VideoFilter() filter = VideoFilter()
filter.blackframe(1, 2).crop(792) filter.blackframe(1, 2).crop(792)
self.assertEqual(list(filter), ['-vf', self.assertEqual(list(filter), ['-vf', 'blackframe=1:2,crop=792'])
'blackframe=1:2,crop=792'])
output = Output('/new', filter) output = Output('/new', filter)
self.assertEqual(list(output), ['-vf', self.assertEqual(
'blackframe=1:2,crop=792', '/new']) list(output), ['-vf', 'blackframe=1:2,crop=792', '/new'])
def test_ffmpeg_interface(self): def test_ffmpeg_interface(self):
input = Input('/old') input = Input('/old')
@ -210,5 +208,113 @@ class VideoFilterTestCase(unittest.TestCase):
self.prefix('yadif=0:-1')) self.prefix('yadif=0:-1'))
class VideoCodecTestCase(unittest.TestCase):
def setUp(self):
self.codec = VideoCodec('libx264')
def prefix(self, *args):
return ['-vcodec', 'libx264'] + list(args)
def test_bitrate(self):
self.codec.bitrate('300k')
self.assertEqual(list(self.codec),
self.prefix('-b', '300k'))
def test_frames(self):
self.codec.frames(100)
self.assertEqual(list(self.codec),
self.prefix('-vframes', '100'))
def test_fps(self):
self.codec.fps(24)
self.assertEqual(list(self.codec),
self.prefix('-r', '24'))
def test_aspect(self):
self.codec.aspect(16, 9)
self.assertEqual(list(self.codec),
self.prefix('-aspect', '16:9'))
def test_bitrate_tolerance(self):
self.codec.bitrate_tolerance(10)
self.assertEqual(list(self.codec),
self.prefix('-bt', '10'))
def test_max_bitrate(self):
self.codec.max_bitrate('100k')
self.assertEqual(list(self.codec),
self.prefix('-maxrate', '100k'))
def test_min_bitrate(self):
self.codec.min_bitrate('50k')
self.assertEqual(list(self.codec),
self.prefix('-minrate', '50k'))
def test_buffer_size(self):
self.codec.buffer_size('20k')
self.assertEqual(list(self.codec),
self.prefix('-bufsize', '20k'))
def test_pass_number(self):
self.codec.pass_number(2)
self.assertEqual(list(self.codec),
self.prefix('-pass', '2'))
def test_language(self):
self.codec.language('DEU')
self.assertEqual(list(self.codec),
self.prefix('-vlang', 'DEU'))
def test_same_quality(self):
self.codec.same_quality()
self.assertEqual(list(self.codec),
self.prefix('-sameq'))
def test_preset(self):
self.codec.preset('max')
self.assertEqual(list(self.codec),
self.prefix('-vpre', 'max'))
class AudioTestCase(unittest.TestCase):
def setUp(self):
self.codec = AudioCodec('AC3')
def prefix(self, *args):
return ['-acodec', 'AC3'] + list(args)
def test_frames(self):
self.codec.frames(100)
self.assertEqual(list(self.codec),
self.prefix('-aframes', '100'))
def test_frequence(self):
self.codec.frequence(48000)
self.assertEqual(list(self.codec),
self.prefix('-ar', '48000'))
def test_bitrate(self):
self.codec.bitrate('320k')
self.assertEqual(list(self.codec),
self.prefix('-ab', '320k'))
def test_quality(self):
self.codec.quality(8)
self.assertEqual(list(self.codec),
self.prefix('-aq', '8'))
def test_language(self):
self.codec.language('DEU')
self.assertEqual(list(self.codec),
self.prefix('-alang', 'DEU'))
def test_preset(self):
self.codec.preset('max')
self.assertEqual(list(self.codec),
self.prefix('-apre', 'max'))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()