Batch replace audio using ffmpeg - macos

I have a folder with mkv and aac files on my Mac. I have used ffmpeg to replace audio in mkv files with success but I can't figure out how to loop it in a folder. Let's say I have a folder with vid1.mkv, vid1.aac, vid2.mkv, vid2.aac etc. I tried this but it doesn't work:
for i in *.mkv; do ffmpeg -i "$i" -i "${i%.*}.aac" -c copy -map 0:v:0 -map 1:a:0 "${i%.*}.remux.mp4" done

Related

How to save files in a different location after conversion with FFMpeg

I am using FFMpeg on Windows to add the same audio to multiple videos using the following line of code:
for %i in (*.mp4) do ffmpeg -y -i "%i" -i m.mp3 -af apad -map 0:v -map 1:a -c:v copy -shortest "%~ni with audio.mp4"
The problem is that the program saves the output files in the same location. Is there any way that I can save them in another location?
you can tell FFmpeg to output to a folder like this:
ffmpeg -i input.mp3 path\to\some\folder\output.mp4

How to I convert all audio tracks to eac3 and keep all subtitles?

I'm not familiar with ffmpeg, but came across this script that takes in the file and creates an output with eac3 audio.
#!/bin/sh
echo "Dolby Digital Plus Muxer"
echo "Developed by #kdcloudy, not affiliated with Dolby Laboratories"
echo "Enter the file name to be converted: "
read filepath
if [! -d $filepath]
then
exit $err
fi
ffmpeg -i $filepath -vn ddp.eac3
ffmpeg -i $filepath -i ddp.eac3 -vcodec copy -c:a eac3 -map 0:s -map 0:v:0 -map 1:a:0 output.mp4
rm ddp.eac3
I'd like to know what to modify in this code to ensure all the subtitles are copied from the original file and all the available audio tracks are converted to eac3 and added to the output.mp4 file.
For the subtitles copying I tried -map but couldn't get it to work. Thanks for the help!
You only need one ffmpeg command:
ffmpeg -i input.mkv -map 0 -c:v copy -c:a eac3 -c:s copy output.mkv
-map 0 Selects all streams. Otherwise only one stream per stream type will be selected. See FFmpeg Wiki: Map for more into on -map.
-c:v copy Stream copy all video.
-c:a eac3 Encodes all audio to E-AC-3.
-c:s copy Stream copy all subtitles.
For compatibility this assumes that the input and output are both Matroska (.mkv).
That script is not great. Here's a cleaner, simpler version (not that I think a script is necessary for this):
#!/bin/bash
# Usage: ./eac3 input.mkv output.mkv
ffmpeg -i "$1" -map 0 -c:v copy -c:a eac3 -c:s copy "$2"
If you want to convert a whole directory see How do you convert an entire directory with ffmpeg?

Using ffmpeg to convert mp3 to mp4 - how to draw filename on generated video?

Using trial and error I am using the following script on an OSX, to bulk convert a whole folder full of mp3 files, to mp4, by looping a specific video file:
for i in *.mp3; do /usr/local/bin/ffmpeg -stream_loop -1 -i /path_to_filename.mp4 -c copy -v 0 -f nut - | /usr/local/bin/ffmpeg -thread_queue_size 10K -i - -i "$i" -c copy -map 0:v -map 1:a -shortest "$(basename "$i" )".mp4 ; done; for f in *.mp3.mp4; do mv -v "$f" "${f/.mp3.mp4/.mp4}"; done
How can I also print/add/burn the mp3 filename, without the extension (.mp3), as an additional video layer at the bottom of the generated video screen, and with the added difficulty of word wrapping the text if is too long?
This command makes a temporary SRT file for the subtitles filter which will automatically deal with the placement and word wrapping:
for i in *.mp3; do echo "1" > subs.srt; echo "00:00:00,000 --> 10:00:00,000" >> subs.srt; echo "${i%.*}" >> subs.srt; ffmpeg -stream_loop -1 -i video.mp4 -i "$i" -filter_complex "[0:v]subtitles=subs.srt:force_style=Alignment=3,format=yuv420p[v]" -map "[v]" -map 1:a -c:v libx264 -c:a copy -shortest -movflags +faststart "${i%.*}.mp4"; done
Running the command in the directory containing the file allows avoidance of basename and creates a simpler command.
MP3 is not universally supported in MP4. Consider changing -c:a copy to -c:a aac if your player does not support it. But I suspect you're targeting YouTube which will be fine with MP3 in MP4.
The three instances of echo are inefficient but effective in avoiding any newline issues. Using one instance of printf would be more optimal, but I don't have access to macOS to test its printf implementation.

Add subtitles to multiple files at once

I have a folder with episodes called ep and a folder with subtitles called sub
Each episode has corresponding subtitles and i need to bulk add them with ffmpeg.
I've read that i can add subtitles with the following command:
ffmpeg -i video.avi -vf "ass=subtitle.ass" out.avi
But that only does it one file at a time.
Is there a bulk variant?
Some useful info:
ls ep prints
<series name> - Ep<episode number>.mkv
ls sub prints
<series name> - Ep<episode number>.ass
I made a small sh script that will do this:
#!/bin/sh
SUBTITLES_FOLDER=sub
EPISODES_FOLDER=ep
OUTPUT_FOLDER=out
for i in "$EPISODES_FOLDER"/*.mkv; do
sub="$SUBTITLES_FOLDER/$(echo "$i" | sed 's/mkv$/ass/')"
ffmpeg -i "$i" -i "$sub" -c:v copy -c:a copy -c:s copy -map 0:0 -map 0:1 -map 1:0 -y "$OUTPUT_FOLDER/$i" &
done
Note the '&' at the end of the ffmpeg command: it makes sure ffmpeg runs in parallel (is this the correct term for it?)
You may want to modify the file extensions and check if ffmpeg supports subtitles with your format, the rest will be done by itself.

replace a word in subtitle with ffmpeg

I want to use ffmpeg to replace all occurrences of a word in all subtitles of a video file with ffmpeg. All non-subtitles channels should be copied (not reencoded) and all formatting from the original subtitles should stay if possible.
example:
ffmpeg -i input.mkv -SUBTITLEFILER='old_word/new_word' output.mkv
I am using ubuntu 19.04 and bash (in case additional steps or dependencies would be required for this)
ffmpeg has no find/replace functionality for subtitles, but you can do this losslessly in 3 commands:
Extract the subtitles:
ffmpeg -i input.mkv -map 0:s:0 -c copy sub0.ass -map 0:s:1 -c copy sub1.ass -map 0:s:2 -c copy sub2.ass
I'm assuming your subtitles are SubStation Alpha (ASS/SSA) subtitles. Use the appropriate output name if they differ: such as .srt for SubRip (refer to ffmpeg -muxers).
Replace with sed:
sed -i 's/cat/dog/g' *.ass
Remux:
ffmpeg -i input.mkv -i sub0.ass -i sub1.ass -i sub2.ass -map 0 -map -0:s -map 1 -map 2 -map 3 -c copy -metadata:s:s:0 language=fas -metadata:s:s:1 language=eng -metadata:s:s:2 language=fin output.mkv
If you want to make a certain subtitle the default see the -disposition option as shown in ffmpeg set subtitles track as default.

Resources