11

Does anyone have an idea of how I can put an image mask over the video without changing the audio & video codec?

I'm making different media files for testing purposes and I want control over my audio and video codecs used in a A/V container, now I need to put an image mask over a A/V file, without changing the audio and video codec.

When using ffmpeg -i video.avi -i image.png -filter_complex 'overlay' avi.mkv I can add -acodec copy but not -vcodec copy, this gives the error:

Streamcopy requested for output streaam 0:0, which is fed from a complex filtergraph. Filtering and streamcopy cannot be used together.

And when just using the above command FFmpeg encodes my streams to another format (MPEG-4 & MP3)

slhck
  • 235,242
Jan Claes
  • 211

3 Answers3

9

You answered your own question: filters are incompatible with copy. You're using a video filter there, so you can't use -vcodec copy or -c:v copy; if you were using an audio filter, you would be unable to to use -acodec copy or -c:a copy.

copy, as its name suggests, copies the stream specified exactly, with no changes. Filters alter the stream(s) they target. By definition, copy and filters are incompatible.

If you simply want to choose a specific video codec, then that's simple enough: use -c:v [codecname]; you can see a list of all the codecs your ffmpeg supports with

ffmpeg -codecs
evilsoup
  • 14,056
1

Since this is for testing simply set a codec with near original quality or even a post-processing format like dnxhd.

# Convert with near original quality compression
ffmpeg -i video.avi -i image.png -filter_complex 'overlay' -vcodec libx265 -crf 10 output.avi

We use libx265 since it yields very high quality video and highly available. A low CRF yields best results with 10 being near original video.

Pithikos
  • 1,654
0

In case it helps anyone, it should be noted that there is probably a somewhat ugly way to do what you want by combining ffprobe and ffmpeg using bash. If you have ffmpeg installed, chances are you have ffprobe too. As a simple audio-only example, the following worked for me, though in principle something similar should be achievable with multiple streams of different kinds.

ffmpeg -i neil_young_tell_me_why.wav -af aresample=resampler=soxr:precision=33:cheby=true -ar 96000 -acodec `ffprobe -v error -show_entries:a:0 stream=codec_name -of default=noprint_wrappers=1:nokey=1 neil_young_tell_me_why.wav | xargs echo -n` neil_young_tell_me_why_96Kup.wav

Explanation: The output of the ffprobe command within the backticks gets expanded in-place to stream 0 of the input file's audio codec, with the newline stripped off by xargs. ffprobe has been set to output a minimal amount of text, and the output of ffprobe's default "writer" has been configured to strip out all other extraneous text, such as labels, etc, when writing to the screen.

I wanted to test higher quality resampling with the SoX resampler so I upsampled a wav file from 44.1KHz to 96KHz while keeping the same codec. Without doing it this way, the codec being chosen automatically by ffmpeg had a lower bit depth, causing the resolution to go down from 24 bit to 16 bit. This way there was no loss of precision.