So my epiphany on the mapping and codec choice front -- I always tried to avoid "multiple codec spec" message -- is that if your media is simple enough, negative mapping is the way to go and you should always choose -c copy flag right off the bat. Here's why: if you have a media file that contains ASS subs, several TTF attachments, jpeg/mjpeg video stream attachments, those don't necessarily show in a mediainfo or regular ffprobe that you might use to investigate how you'd be batch encoding similar/same media (e.g. remuxed/ripped Blurays).
If you do a -map 0 or -map 0:v, you'll grab those mjpegs and a -c:v hevc_qsv will try to convert them, which is NOT what you want. Furthermore, if you only map your subs and not your attachments, you lose styling pretty much entirely. Plus, occasionally attachments are problematic. So with a simple file, say it has three audio tracks, four subtitle tracks. You don't know about images or attachments -- you could dig in and figure it out, but why bother? Figure out which of the tracks you DON'T want and use the stream indices -- I prefer stream-specific indices, like the following:
In this way, you map EVERYTHING, set it all to be copied, and override individual preferences. So in this case, maybe I'm copying the lossless DTS-MA, turning the DD+ into a low-quality stereo track, and converting just the main video track into HEVC while leaving any other possible video tracks (i.e., m/jpeg video images) alone. You can strip these out with explicit maps, but it's easier to leave them alone and it doesn't hurt anything to copy them over unless you're trying to REALLY slim down your files. Note, very importantly, that I'm using a stream specifier on my c:v flag, so it becomes c:v:0 to avoid causing ffmpeg to try and convert any possible m/jpeg streams to convert using whatever codec I've specified, which will cause the process to error out. There might be more eloquent ways to avoid this, but there's no training here...just figuring it the f**k out.
This method also ensures you keep all attachments (TTF files for ASS styling) and should keep HDR/DV metadata. I'm not sure that it keeps side data, however. You can dump that to a file with a flag, but I couldn't figure out how to keep that with the file. I have, however, re-encoded a LOT of DV content to AV1 with this method that now parses as DV, even though AV1 does not support DV.
More complex media definitely require explicit mapping, but -c copy is still something I can't recommend enough. Even if you're re-encoding just about everything. Use -map 0:v to grab all possible jpeg streams or -map 0:v:0 to only grab the main video stream, if you have to map streams explicitly (e.g., there are 40+ streams present and you only want...four), you can still use some tricks.
Language mapping (all media streams that match specified language):
Optional mapping (example -- map all attachments that might exist, won't cause errors if no attachments, just skips):
Make sure you still use -c copy right after your maps as a standard practice, even if you're converting all known streams. You're likely catching streams you don't know about...or you might want to catch streams that you don't know about.
If you do a -map 0 or -map 0:v, you'll grab those mjpegs and a -c:v hevc_qsv will try to convert them, which is NOT what you want. Furthermore, if you only map your subs and not your attachments, you lose styling pretty much entirely. Plus, occasionally attachments are problematic. So with a simple file, say it has three audio tracks, four subtitle tracks. You don't know about images or attachments -- you could dig in and figure it out, but why bother? Figure out which of the tracks you DON'T want and use the stream indices -- I prefer stream-specific indices, like the following:
Code:
ffmpeg -i in.mkv -map 0 -map -0:a:2 -map -0:s:2 -map -0:s:3 -c copy -c:v:0 hevc_qsv -preset slow -crf 20 -c:a:1 libopus -b:a:1 128k -ac:a:1 2 -filter:a:1 "<filtergraph>" out.mkv
In this way, you map EVERYTHING, set it all to be copied, and override individual preferences. So in this case, maybe I'm copying the lossless DTS-MA, turning the DD+ into a low-quality stereo track, and converting just the main video track into HEVC while leaving any other possible video tracks (i.e., m/jpeg video images) alone. You can strip these out with explicit maps, but it's easier to leave them alone and it doesn't hurt anything to copy them over unless you're trying to REALLY slim down your files. Note, very importantly, that I'm using a stream specifier on my c:v flag, so it becomes c:v:0 to avoid causing ffmpeg to try and convert any possible m/jpeg streams to convert using whatever codec I've specified, which will cause the process to error out. There might be more eloquent ways to avoid this, but there's no training here...just figuring it the f**k out.
This method also ensures you keep all attachments (TTF files for ASS styling) and should keep HDR/DV metadata. I'm not sure that it keeps side data, however. You can dump that to a file with a flag, but I couldn't figure out how to keep that with the file. I have, however, re-encoded a LOT of DV content to AV1 with this method that now parses as DV, even though AV1 does not support DV.
More complex media definitely require explicit mapping, but -c copy is still something I can't recommend enough. Even if you're re-encoding just about everything. Use -map 0:v to grab all possible jpeg streams or -map 0:v:0 to only grab the main video stream, if you have to map streams explicitly (e.g., there are 40+ streams present and you only want...four), you can still use some tricks.
Language mapping (all media streams that match specified language):
Code:
-map 0:m:language:eng
Optional mapping (example -- map all attachments that might exist, won't cause errors if no attachments, just skips):
Code:
-map 0:t?
Jellyfin 10.10.0 LSIO Docker | Ubuntu 24.04 LTS | i7-13700K | Arc A380 6 GB | 64 GB RAM | 79 TB Storage