replace a word in subtitle with ffmpeg - bash

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.

Related

Hardcoding subtitles from DVD or VOB file with ffmpeg

I have some DVDs that I would like to encode so that I can play them on a Chromecast, with subtitles. It seems that Chromecast only supports text-based subtitle formats, while DVD subtitles are in a bitmap format, so I need to hardcode the subtitles onto the video stream.
First I use vobcopy to create a VOB file:
vobcopy -I /dev/sr0
Next I want to use ffmpeg to encode it as a video stream in a format that is supported by the Chromecast. This is the closest I've come so far (based on the ffmpeg documentation):
ffmpeg -analyzeduration 100M -probesize 100M -i in.vob \
-filter_complex "[0:v:0][0:s:0]overlay[vid]" -map "[vid]" \
-map 0:3 -codec:v libx264 -crf 20 -codec:a copy out.mkv
The -filter_complex "[0:v:0] [0:s:0]overlay[vid] parameters should overlay the first subtitle stream on the first video stream (-map 0:3 is for the audio). This partially works, but the subtitles are only shown for a fraction of a second (I'm guessing one frame).
How can I make the subtitles display for the correct duration?
I'm using ffmpeg 4.4.1 on Linux, but I've also tried the latest snapshot version, and tried gstreamer and vlc (but didn't get far).
The only solution I found that worked perfectly was a tedious multi-stage process.
Copy the DVD with vobcopy
vobcopy -I /dev/sr0
Extract the subtitles in vobsub format using mencoder. This command will write subs.idx and subs.sub. The idx file can be edited if necessary to tweak the appearance of the subtitles.
mencoder *.vob -nosound -ovc frameno -o /dev/null \
-vobsuboutindex 0 -sid 0 -vobsubout subs
Copy the audio and video from the VOB into an mkv file. ffprobe can be used to identify the relevant video and audio stream numbers.
ffmpeg -fflags genpts -i *vob -map 0:1 -map 0:3 \
-codec:v copy -codec:a copy copied_av.mkv
Merge the subtitles with the audio/video stream.
mkvmerge -o merged.mkv copied_av.mkv subs.sub subs.idx
Then ffmpeg will work reliably with the mkv file to write hardcoded subtitles to the video stream.
ffmpeg -i merged.mkv -filter_complex "[0:v:0][0:s:0]overlay[vid]" \
-map [vid] -map 0:1 -codec:v libx264 -codec:a copy hardcoded.mkv

ffmpeg add video thumbnail only [duplicate]

I am trying to find the proper ffmpeg command to add a .png or .jpg image to a .mp4 video as a thumbnail. The command will eventually automatically be executed by a C# program.
This is what I have so far:
# This does not work. It only removes the default thumbnail.
ffmpeg -i video.mp4 -i image.png -acodec copy -vcodec copy -map 0 -map 1:0 OUTPUT.mp4
Is what I want possible with ffmpeg? If so, please guide me in the right direction.
Using ffmpeg 4.0, released Apr 20 2018 or newer,
ffmpeg -i video.mp4 -i image.png -map 1 -map 0 -c copy -disposition:0 attached_pic out.mp4
As in version 4.2.2...See Section 5.4 in FFmpeg documentation
To add an embedded cover/thumbnail:
ffmpeg -i in.mp4 -i IMAGE -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic out.mp4
Not all muxers support embedded thumbnails, and those who do, only support a few formats, like JPEG or PNG.

How to add multiple audio files at specific times, on a silence audio file using ffmpeg?

I need to overlay audio files at specific times, on an existing silence.mp3. Something like that:
[----[...audio1...]----------[...audio2...]---------------]
I've tried the following but it doesn't work:
ffmpeg -y -i silence.mp3 -itsoffset 4 -i audio1.mp3 -itsoffset 30 -i audio2.mp3 -c:a copy final.mp3
Any help would be appriciated. Thank you.
There are several methods.
adelay, amix
Use the adelay and amix filters:
ffmpeg -i audio1.mp3 -i audio2.mp3 -filter_complex "[0]adelay=4s:all=1[0a];[1]adelay=30s:all=1[1a];[0a][1a]amix=inputs=2[a]" -map "[a]" output.mp3
Note that the amix filter will reduce volume of the output to prevent clipping. Followup with dynaudnorm or volume filters if desired.
adelay, concat filter
Or adelay and concat filters. This assumes audio1.mp4 is 10 seconds long, and both inputs have the same sample rate and channel layout:
ffmpeg -i audio1.mp3 -i audio2.mp3 -filter_complex "[0]adelay=4s:all=1[0a];[1]adelay=16s:all=1[1a];[0a][1a]concat=n=2:v=0:a=1[a]" -map "[a]" output.mp3
anullsrc, concat demuxer
Or generate silent files as spacers with the anullsrc filter:
ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -t 4 4.mp3
ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -t 16 16.mp3
Create input.txt:
file '4.mp3'
file 'audio1.mp3'
file '16.mp3'
file 'audio2.mp3'
Then use the concat demuxer:
ffmpeg -f concat -i input.txt -c copy output.mp3

How do I add a custom thumbnail to a .mp4 file using ffmpeg?

I am trying to find the proper ffmpeg command to add a .png or .jpg image to a .mp4 video as a thumbnail. The command will eventually automatically be executed by a C# program.
This is what I have so far:
# This does not work. It only removes the default thumbnail.
ffmpeg -i video.mp4 -i image.png -acodec copy -vcodec copy -map 0 -map 1:0 OUTPUT.mp4
Is what I want possible with ffmpeg? If so, please guide me in the right direction.
Using ffmpeg 4.0, released Apr 20 2018 or newer,
ffmpeg -i video.mp4 -i image.png -map 1 -map 0 -c copy -disposition:0 attached_pic out.mp4
As in version 4.2.2...See Section 5.4 in FFmpeg documentation
To add an embedded cover/thumbnail:
ffmpeg -i in.mp4 -i IMAGE -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic out.mp4
Not all muxers support embedded thumbnails, and those who do, only support a few formats, like JPEG or PNG.

FFmpeg simple 1:1 overlay and concatenate?

I am using ffmpeg on Ubuntu 14.04 (Jon Severinsson's PPA) and am playing video files out of a folder - one by one.
First question I wasn't able to figure out yet - how can I add a simple overlay - 720p footage with 720p overlay (with partial transparency)? So there is no resize or alignment needed - just the 1:1 overlay. I tried a lot already with -vf and -filter_complex but didn't show up.
Second question - with concatenate, is it possible to have the switches between the files seamless? Best without creating a new file - so, on the fly? I need to reduce the gaps between the file switches or eliminate them completely.
This is my bash right now:
#!/usr/bin/env bash
while :; do
files=(*)
ffmpeg -re -i "${files[$RANDOM % ${#files[#]}]}" -acodec copy -vcodec copy -f flv ServerAddress
done
So I have everything in /vod - the videofiles, as well as the overlay.png
Thanks a bunch in advance,
Tim
For the overlay you need to scale the image to the original source dimensions.
To concat multiple source files that have the same codec use the concat demuxer.
Eg:
Make a playlist.txt with the following format:
file '/path/to/file_1'
file '/path/to/file_2'
file '/path/to/file_3'
[..]
And then:
ffmpeg -f concat -i playlist.txt -i overlay.png -filter_complex "[1:v] scale=1280:720 [ovr];[0:v][ovr] overlay=0:0" ...
If the video and the image are the same size you can just use:
ffmpeg -f concat -i playlist.txt -i overlay.png -filter_complex "[0:v] overlay"
Update:
Full example:
You cannot filter and copy the video stream at the same time!
ffmpeg -re -f concat -i playlist.txt -i overlay.png -filter_complex "[0:v] overlay" -c:v h264 -c:a libfdk_aac -ar 44100 -f flv rtmp://...
If your audio stream is valid and has one of the supported audio rates (44100, 22050, 11025) you can do:
ffmpeg -re -f concat -i playlist.txt -i overlay.png -filter_complex "[0:v] overlay" -c:v h264 -c:a copy -f flv rtmp://...

Resources