mirror of
https://github.com/kkroening/ffmpeg-python.git
synced 2025-04-05 04:22:51 +08:00
Add .audio
+ .video
operators
This commit is contained in:
parent
41daf9a953
commit
881ae4efff
@ -104,10 +104,10 @@ With additional filtering:
|
||||
```python
|
||||
in1 = ffmpeg.input('in1.mp4')
|
||||
in2 = ffmpeg.input('in2.mp4')
|
||||
v1 = in1['v'].hflip()
|
||||
a1 = in1['a']
|
||||
v2 = in2['v'].filter('reverse').filter('hue', s=0)
|
||||
a2 = in2['a'].filter('areverse').filter('aphaser')
|
||||
v1 = in1.video.hflip()
|
||||
a1 = in1.audio
|
||||
v2 = in2.video.filter('reverse').filter('hue', s=0)
|
||||
a2 = in2.audio.filter('areverse').filter('aphaser')
|
||||
joined = ffmpeg.concat(v1, a1, v2, a2, v=1, a=1).node
|
||||
v3 = joined[0]
|
||||
a3 = joined[1].filter('volume', 0.8)
|
||||
|
@ -53,8 +53,8 @@ class Stream(object):
|
||||
Process the audio and video portions of a stream independently::
|
||||
|
||||
input = ffmpeg.input('in.mp4')
|
||||
audio = input[:'a'].filter("aecho", 0.8, 0.9, 1000, 0.3)
|
||||
video = input[:'v'].hflip()
|
||||
audio = input['a'].filter("aecho", 0.8, 0.9, 1000, 0.3)
|
||||
video = input['v'].hflip()
|
||||
out = ffmpeg.output(audio, video, 'out.mp4')
|
||||
"""
|
||||
if self.selector is not None:
|
||||
@ -63,6 +63,56 @@ class Stream(object):
|
||||
raise TypeError("Expected string index (e.g. 'a'); got {!r}".format(index))
|
||||
return self.node.stream(label=self.label, selector=index)
|
||||
|
||||
@property
|
||||
def audio(self):
|
||||
"""Select the audio-portion of a stream.
|
||||
|
||||
Some ffmpeg filters drop audio streams, and care must be taken
|
||||
to preserve the audio in the final output. The ``.audio`` and
|
||||
``.video`` operators can be used to reference the audio/video
|
||||
portions of a stream so that they can be processed separately
|
||||
and then re-combined later in the pipeline. This dilemma is
|
||||
intrinsic to ffmpeg, and ffmpeg-python tries to stay out of the
|
||||
way while users may refer to the official ffmpeg documentation
|
||||
as to why certain filters drop audio.
|
||||
|
||||
``stream.audio`` is a shorthand for ``stream['a']``.
|
||||
|
||||
Example:
|
||||
Process the audio and video portions of a stream independently::
|
||||
|
||||
input = ffmpeg.input('in.mp4')
|
||||
audio = input.audio.filter("aecho", 0.8, 0.9, 1000, 0.3)
|
||||
video = input.video.hflip()
|
||||
out = ffmpeg.output(audio, video, 'out.mp4')
|
||||
"""
|
||||
return self['a']
|
||||
|
||||
@property
|
||||
def video(self):
|
||||
"""Select the video-portion of a stream.
|
||||
|
||||
Some ffmpeg filters drop audio streams, and care must be taken
|
||||
to preserve the audio in the final output. The ``.audio`` and
|
||||
``.video`` operators can be used to reference the audio/video
|
||||
portions of a stream so that they can be processed separately
|
||||
and then re-combined later in the pipeline. This dilemma is
|
||||
intrinsic to ffmpeg, and ffmpeg-python tries to stay out of the
|
||||
way while users may refer to the official ffmpeg documentation
|
||||
as to why certain filters drop audio.
|
||||
|
||||
``stream.video`` is a shorthand for ``stream['v']``.
|
||||
|
||||
Example:
|
||||
Process the audio and video portions of a stream independently::
|
||||
|
||||
input = ffmpeg.input('in.mp4')
|
||||
audio = input.audio.filter("aecho", 0.8, 0.9, 1000, 0.3)
|
||||
video = input.video.hflip()
|
||||
out = ffmpeg.output(audio, video, 'out.mp4')
|
||||
"""
|
||||
return self['v']
|
||||
|
||||
|
||||
def get_stream_map(stream_spec):
|
||||
if stream_spec is None:
|
||||
|
@ -175,10 +175,15 @@ def test_combined_output():
|
||||
]
|
||||
|
||||
|
||||
def test_filter_with_selector():
|
||||
@pytest.mark.parametrize('use_shorthand', [True, False])
|
||||
def test_filter_with_selector(use_shorthand):
|
||||
i = ffmpeg.input(TEST_INPUT_FILE1)
|
||||
v1 = i['v'].hflip()
|
||||
a1 = i['a'].filter('aecho', 0.8, 0.9, 1000, 0.3)
|
||||
if use_shorthand:
|
||||
v1 = i.video.hflip()
|
||||
a1 = i.audio.filter('aecho', 0.8, 0.9, 1000, 0.3)
|
||||
else:
|
||||
v1 = i['v'].hflip()
|
||||
a1 = i['a'].filter('aecho', 0.8, 0.9, 1000, 0.3)
|
||||
out = ffmpeg.output(a1, v1, TEST_OUTPUT_FILE1)
|
||||
assert out.get_args() == [
|
||||
'-i', TEST_INPUT_FILE1,
|
||||
@ -273,7 +278,7 @@ def test_filter_concat__audio_only():
|
||||
def test_filter_concat__audio_video():
|
||||
in1 = ffmpeg.input('in1.mp4')
|
||||
in2 = ffmpeg.input('in2.mp4')
|
||||
joined = ffmpeg.concat(in1['v'], in1['a'], in2.hflip(), in2['a'], v=1, a=1).node
|
||||
joined = ffmpeg.concat(in1.video, in1.audio, in2.hflip(), in2['a'], v=1, a=1).node
|
||||
args = (
|
||||
ffmpeg
|
||||
.output(joined[0], joined[1], 'out.mp4')
|
||||
@ -298,7 +303,7 @@ def test_filter_concat__wrong_stream_count():
|
||||
in1 = ffmpeg.input('in1.mp4')
|
||||
in2 = ffmpeg.input('in2.mp4')
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
ffmpeg.concat(in1['v'], in1['a'], in2.hflip(), v=1, a=1).node
|
||||
ffmpeg.concat(in1.video, in1.audio, in2.hflip(), v=1, a=1).node
|
||||
assert str(excinfo.value) == \
|
||||
'Expected concat input streams to have length multiple of 2 (v=1, a=1); got 3'
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user