I'm trying to do some simple stream selection. Using ffmpeg directly, I'd use the map option. However, when trying to do this using ffmpeg-python, I can't seem to get it correct. The map argument is getting put into a bracket, which doesn't work.
>>> import ffmpeg
>>> infile = ffmpeg.input('test.mkv')
>>> stream = infile['1']
>>> outfile = ffmpeg.output(stream, 'test-out.mkv')
>>> ffmpeg.compile(outfile)
['ffmpeg', '-i', 'test.mkv', '-map', '[0:1]', 'test-out.mkv']
This fails with the error Output with label '0:1' does not exist in any defined filter graph, or was already used elsewhere.
What is the proper way to do stream selection when you don't need complex video graphs?
what you need may be: infile[0:'v']
That throws an exception.
>>> stream = infile[0:'v']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/project/env/lib/python3.5/site-packages/ffmpeg/nodes.py", line 63, in __getitem__
raise TypeError("Expected string index (e.g. 'a'); got {!r}".format(index))
TypeError: Expected string index (e.g. 'a'); got slice(0, 'v', None)
sorry, i misunderstand what you mean, if you only want to select some streams from source to output without any filters ,i think you can use "map" option of ffmpeg, eg:
infile = ffmpeg.input('test.mkv')
outfile = ffmpeg.output(infile, 'test-out.mkv', map="0:v")
ffmpeg.run(outfile)
Thanks @alphabetaxz. We're getting real close. While that worked for a single stream, I can't use it for multiple streams since you can't duplicate kwargs.
So I can't do the equivalent of ffmpeg -i test.mkv -map 0:1 -map 0:2 out.mkv
Since the kwargs get passed verbatim, I tried to get clever and do this outfile = ffmpeg.output(infile, 'test-out.mkv', map="0:1 -map 0:2") but the space doesn't compile right and everything after the 0:1 is ignored.
Any ideas?
sorry , about this
@whichken What's the raw ffmpeg command you're trying to emulate with ffmpeg-python?
_(edit)_: Oh I see:
ffmpeg -i test.mkv -map 0:1 -map 0:2 out.mkv
Ok yeah, we need to figure out a way to support this. AFAICT there's no way to do this currently, or at least not in any reasonable manner.
@whichken I think your example syntax in the first comment makes the most sense:
import ffmpeg
infile = ffmpeg.input('test.mkv')
outfile = ffmpeg.output(infile['1'], 'test-out.mkv')
And similarly for multiple streams:
infile = ffmpeg.input('test.mkv')
outfile = ffmpeg.output(infile['1'], infile['2'], 'test-out.mkv')
I consider it a bug that -map [0:1] is produced instead of -map 0:1. Will try to make a fix soon.
Also, the [] operator should probably be able to accept integers (in addition to strings, as currently supported).
Or perhaps eventually this shorthand would make things simpler:
infile = ffmpeg.input('test'.mk4')
outfile = ffmpeg.output(infile[[1, 2]], 'test-out.mkv')
or fluently:
(
ffmpeg
.input('test.mk4')
[[1, 2]]
.output('test-out.mkv')
.run()
)
The [] operator would basically take either a single identifier (e.g. ['v']) or a list of identifiers (e.g. [[1, 2]]). This is similar to how a library like Pandas operates.
All those options look great.
I was going to suggest that the produced -map [0:1] was a bug, but I'm not familiar enough with ffmpeg to know if that was some other format that I was unfamiliar with.
Let me know if I can help out at all.
@whichken If you get a chance, let me know if #103 fixes this for you.
Regardless, I'll merge it in the next day or so if I don't hear back.
@kkroening I can confirm that this fixes my issue. Thanks for the quick turn around!
@kkroening
regarding:
ffmpeg -i test.mkv -map 0:1 -map 0:2 out.mkv
Ok yeah, we need to figure out a way to support this. AFAICT there's no way to do this currently, or at least not in any reasonable manner.
is there a workaround for it now?
Most helpful comment
@whichken I think your example syntax in the first comment makes the most sense:
And similarly for multiple streams:
I consider it a bug that
-map [0:1]is produced instead of-map 0:1. Will try to make a fix soon.