====== Video Editing on the Command Line ======
===== ffmpeg Recipes =====
The problem: I have recorded about **95 video clips** using the **XiaoYi Yi** action camera. They make a total of about **20 Gb** of data and **3.7 hours** of play. I want to make some **video editing** with the following guidelines:
- Work from the **command line**, using **scripts** to do all the work. I don't want to use non-linear video editing software, which are very resource hungry and requires big screens.
- **Avoid re-encoding** at all.
- **Cut** the required clips and assemble them in a **freely choosen order**.
- Make some additional clips using **still images** or images with **Ken Burst** effects.
- **No transitions** between clips (cross-fade and alike) are planned at the moment.
To solve step 4, we decided to use the **ffmpeg** tool. We wish to make the still-image clips and the Ken Burst clips using the same features (as far as possibile) of the original videos from the XiaoYi Yi camera, because we want to **concatenate them without re-encoding**.
Using the GNU/Linux tools: **file(1)**, **ffprobe(1)**, **mplayer(1)** and **avidemux** we inspected the Yi videos, determining the following:
^ Frame size | 1920x1080 24bpp |
^ Frames per second | 29.970 |
^ Video codec | H264 |
^ Pixel format | yuvj420p |
^ Video time base | 1/240000 |
^ Types of frame | IPPPPPPPIPPPPPPPI.... (no B-Frames, group of pictures = 8) |
^ Audio codec | AAC |
^ Audio stream | 48000 Hz, 2 ch, floatle |
^ File type | ISO Media, MPEG v4 system, 3GPP JVT AVC [ISO 14496-12:2005] |
To make a vido (file type) much like as possible as the XiamYi camera, we used the the **mp4** muxer (selected automatically by the output filename) with muxer brand set to **avc1** and the **3gp** format:
ffmpeg ... -brand avc1 -f 3gp output.mp4
Other muxer brand availables are: **mp41**, **mp42**, **isom**, **iso2**, ... (discovered inspecting the binary file with ''strings'', which alternatives?).
===== Mixing videos from different sources =====
Sometimes we needed to mix video clips originating from different sources. To apply our simple cut-and-paste recipe (wich preserve the original video quality, without re-encoding), we normalized all the "different" video clips to the same format as the one produced by the Xiaomi Yi camera.
One annoying effect of videos created by joining clips with different encoding parameters, is seen in **mplayer**: if you switch the play at **full screen**, the videos jumps back automatically at **non-full screen** when there is such a clip join.
==== Normalize (Resize and Re-encode) ====
If we want to mix videos from **different sources** (e.g. a smartphone and the Xiaomi Yi camera), we first convert the clips all into **the same format**.
With this recipe we will convert an input video, resizing (upscaling) it and converting it into a format much like as possible as the one produced by the Xiaomi Yi camera. Video format is inspected with the **mediainfo** tool.
ffmpeg -i input_video.mkv \
-r '30000/1001' -aspect '1920:1080' \
-c:v libx264 -vf 'scale=1920:1080:flags=lanczos' \
-profile:v main -level:v 4.0 \
-x264-params \
bitrate=12000:vbv_maxrate=12500:vbv_bufsize=20000:nal_hrd=vbr:keyint=8:bframes=0:scenecut=-1:ref=1
-brand avc1 \
output_video.mp4
**WARNING** The **%%-r%%** option forces frames dropping or frames duplicating as necessary, to obtain the requested FPS (30000/1001 = 29.97). The resulting video will have the same duration as the source, but it can show some jerky shuttering.
^ mediainfo output ^^ ffmpeg option ^
^ Format | MPEG-4 | |
^ Format profile | JVT | -brand avc1 |
^ Codec ID | avc1 (isom/iso2/avc1/mp41) | -brand avc1 |
^ Format | AVC | |
^ Format/Info | Advanced Video Codec | |
^ Format profile | Main@L4 | -profile:v main -level:v 4.0 |
^ Format settings, CABAC | Yes | |
^ Format settings, ReFrames | 1 frame | -x264-params ref=1 |
^ Format settings, GOP | M=1, N=8 | -x264-params keyint=8:bframes=0:scenecut=-1 |
^ Bit rate mode | Variable | -x264-params vbv_maxrate=12000:vbv_bufsize=2000:nal_hrd=vbr |
^ Frame rate | 29.970 (30000/1001) FPS | -r 30000/1001 |
==== Rotate ====
Sometime it is necessary to **rotate a video by 180 degrees** (e.g. a video made with a smartphone, using the wrong orientation). It is necessary to **remove the video rotation metadata** beforehand, because ffmpeg does not seem able to remove them and apply the video filter in a single pass.
ffmpeg -i input_video.mp4 -c copy -metadata:s:v:0 rotate=0 tmp_video.mp4
Then the ffmpeg **transpose** video filter is required, to rotate a video by 180 degrees we need to apply the ''transpose=1'' two times:
ffmpeg -i tmp_video.mp4 -vf transpose=1,transpose=1 rotated_video.mp4
You can apply the transpose and the normalization (if required, see the above paragraph) in a single pass: just add the transpose operation to the whole normalization recipe above.
**INFO**: The number accepted by the transpose filter means:
* 0 = Rotate 90 deg. counterclockwise and do a vertical flip (default)
* 1 = Rotate 90 deg. clockwise
* 2 = Rotate 90 deg. counterclockwise
* 3 = Rotate 90 deg. clockwise and do a vertical flip
A 90-degree rotation involves the problem of the height / width ratio, so a more complex recipe is needed, such as the one described on the page: **[[fix_smartphone_portrait_videos]]**.
==== Add an Audio Track ====
The **time-lapse videos** taken by the Xiaomi Yi Action camera **do not have an audio track**. This causes problems when cutting and concatenating clips with the recipes presented below: you can see the play (with **mplayer**) which **freezes for several seconds** at the joining point of a clip with no audio and a clip with audio.
So I add a silence audio track to theese clips with **ffmpeg**:
ffmpeg -f lavfi -i anullsrc=sample_rate=48000 -i timelapse_video.mp4 \
-shortest -c:a libfdk_aac -b:a 128k -c:v copy timelapse_video_silence.mp4
===== Concatenate the Clips =====
Suppose (see below for the actual recipes) that we have extracted the **choosen clips** from the original videos and made **some extra clips** with ''ffmpeg'' (still-images and Ken Burst effects).
We have also the list of all the clips to make the montage; a file named **clip_list.txt** containing something like this:
file 'clip_001.mp4'
file 'clip_002.mp4'
file 'clip_003.mp4'
...
Now we face **the problem to concatenate all together**. Our first attemp was a failure, read below!
==== Concatenate at File Level: Does NOT Work! ====
Our first attemp was to use the **concat protocol** and the **copy** codec. This works well if all the MP4 files are equal (frame rate, time base, etc.).
# This does not work well!
ffmpeg -f concat -safe 0 -i clip_list.txt -c copy montage.mp4
Unfortunately this was not the case when we mixing clips filmed with the action cam and clips generated with ''ffmpeg''. We think that the problem was the difference in **time_base**; it was **1/240000** for files coming from XiaoYi Yi cam and it was **1/90000** for files produced with ffmpeg. Once played with **mplayer** the montage exhibits some seconds of **freeze** on scene cuts, when switching //time_base//.
We **cannot find a way to set the //time_base//** when producing videos using **ffmpeg**, so we abandoned this way.
==== Concatenate at the Transport Streams Level ====
We found the solution in this page: **[[https://trac.ffmpeg.org/wiki/Concatenate#protocol|the Concatenate protocol]]**. Basically all the streams must be transcoded to an **[[wp>MPEG transport stream]]** and then muxed into an mp4 file. This is a **lossless** operation when using **h.264** video and **AAC** audio.
The trick is to use the appropriate **bitstream filters** (**''%%-bsf%%''** command line option), and produce all the pieces as **mpegts** clips.
==== Recipe to Cut Clips ====
This is the command line to extract (cut) a clip from a larger video, the piece is identified by the starting time (**%%-ss MM:SS.mmm%%**) and its lenght (**%%-t SS.mmm%%**).
ffmpeg -i YDXJ0945.mp4 -ss 01:48.641 -c copy -t 4.538 -bsf:v h264_mp4toannexb -f mpegts clip_242.ts
==== Recipe to Concatenate ====
Suppose that **clip_list.txt** is a text file with the list of //mpegts// clips to concatenate (see above), this is the command line to concatenate all together and make an mp4 file:
ffmpeg -f concat -safe 0 -i clip_list.txt -c copy -bsf:a aac_adtstoasc -brand avc1 -f 3gp montage.mp4
During the process you may get the following error message:
[h264 @ 0x564b14890620] non-existing SPS 0 referenced in buffering period
[h264 @ 0x564b14890620] SPS unavailable in decode_picture_timing
it seems to be harmless, at least according to this **[[https://github.com/get-iplayer/get_iplayer/wiki/faq|FAQ]]**: //These messages comes from the H.264 video decoder in ffmpeg and ar printed when re-muxing MPEG-TS files to MP4. As far as is known, the conditions flagged by ffmpeg do not have any effect on get_iplayer re-muxing, so you can ignore these messages//.
===== Video Clip From a Still-image =====
#!/bin/sh -e
INPUT_FILE="$1" # An MP4 file.
STILLFRAME="$2" # Frame to extract MM:SS.DDD.
DURATION_S="$3" # SS.DDD duration.
OUTPUT_MP4="$4" # Output MP4 video.
STILL_IMG="_stillimage.$$.jpg"
# NOTICE: Put -ss option after -i if cut is not frame precise (slower)!
ffmpeg -loglevel fatal -ss "$STILLFRAME" -i "$INPUT_FILE" -vframes 1 -f image2 "$STILL_IMG"
ffmpeg -loglevel error -y -f lavfi -i 'anullsrc=sample_rate=48000' \
-loop 1 -framerate '29.970' -i "$STILL_IMG" -vf 'scale=1920:1080' -t "$DURATION_S" \
-pix_fmt 'yuvj420p' \
-c:a 'libfaac' \
-c:v 'libx264' -profile 'main' -x264-params 'keyint=8:bframes=0' \
-bsf:v 'h264_mp4toannexb' -f 'mpegts' -r '29.970' "$OUTPUT_MP4"
rm "$STILL_IMG"
**NOTICE**: The resulting video clips have a **start_pts** greather than zero (e.g. 127920), which is different from the videos produced by the XiaoYi camera. It is a common practice to produce videos with the **PTS** (Presentation Time Stamp) of the **first frame greather than zero**; otherwise a subsequent B-Frame may eventually requires a negative **Decode Time Stamp** (DTS), which is bad. This non-zero PTS should not pose any problem in concatenating video clips.
===== Video Clip Ken Burst Effect =====
==== Step 1: make the images ====
This is the **kenburst-1-make-images** Python script. It sends a batch of images to the stdout, making the Ken Burst effect on a image, of the specified duration. The Ken Burst effect is specified by two geometry which identify the start and the end position into the image itself.
#!/usr/bin/python
# Make a batch of images to create a Ken Burst effect on a source image.
import os.path, re, subprocess, sys
if len(sys.argv) < 4:
print "Usage %s " % (os.path.basename(sys.argv[0]),)
sys.exit(1)
# Geometry: "WxH+X+Y" => Width, Height, X (from left), Y (from top)
input_img = sys.argv[1]
geometry = sys.argv[2]
duration_s = float(sys.argv[3])
fps = '29.970'
stdout_mode = True
(geom1, geom2) = geometry.split(':', 1)
(w1, h1, x1, y1) = re.split('x|\+', geom1)
(w2, h2, x2, y2) = re.split('x|\+', geom2)
frames = (int(round(duration_s * float(fps))) - 1)
for f in range(0, (frames + 1)):
percent = float(f) / frames
w = int(float(w1) + (float(w2) - float(w1)) * percent)
h = int(float(h1) + (float(h2) - float(h1)) * percent)
x = int(float(x1) + (float(x2) - float(x1)) * percent)
y = int(float(y1) + (float(y2) - float(y1)) * percent)
crop = '%dx%d+%d+%d!' % (w, h, x, y)
if stdout_mode:
cmd = ['convert', input_img, '-crop', crop, '-resize', '1920x1080!', 'jpeg:-']
else:
cmd = ['convert', input_img, '-crop', crop, '-resize', '1920x1080!', 'frame_%04d.jpg' % (f,)]
print ' '.join(cmd)
subprocess.call(cmd)
==== Step 2: assemble the video ====
This is the **kenburst-2-make-video** shell script. It takes a **batch of images** from the **stdin**, and create a video from them.
#!/bin/sh
# Get a stream of JPG images from stdin, make an MP4 video.
VIDEO_OUT="$1"
if [ -z "$VIDEO_OUT" ]; then
echo "Usage: $(basename $0) "
exit 1
fi
ffmpeg -loglevel error -y -f lavfi -i 'anullsrc=sample_rate=48000' \
-f image2pipe -vcodec mjpeg -framerate '29.970' -i - -shortest \
-c:a 'libfaac' \
-c:v 'libx264' -profile 'main' -x264-params 'keyint=8:bframes=0' \
-bsf:v 'h264_mp4toannexb' -f 'mpegts' -r '29.970' "$VIDEO_OUT"
==== Step 3: pipe all together ====
With this script we will pipe the **output** of **kenburst-1-make-images** script to the **input** of **kenburst-2-make-video**, so it will not save the intermediate images to the disk:
#!/bin/sh -e
#
# Extract a frame from a video, or use a single image
# and make a Ken Burst video of the specified duration.
INPUT_FILE="$1" # The JPG file.
KBURST_GEO="$2" # Ken Burst data: begin and end geometry.
DURATION_S="$3" # SS.DDD duration.
OUTPUT_MP4="$4" # Output MP4 video.
./kenburst-1-make-images "$INPUT_FILE" "$KBURST_GEO" "$DURATION_S" \
| ./kenburst-2-make-video "$OUTPUT_MP4"
====== Re-encoding with tonal correction ======
We had some video clips recorded with an **SJCAM Sj8 Pro** camera with a **bad color balance and saturation** due some bad tables [[..:..:hardware:sjcam-8pro-custom-firmware|loaded into the firmware]]. It is possibile to re-encode all the video clips applying an equalization filter keeping all the encoding paramteres as similar as possibile to the original ones.
The video clips were **extracted from the original MP4 container** as **[[wp>MPEG transport stream|MPEG-TS]]** snippets containing only video (no audio). To re-encode each clip we used the following **ffmpeg** recipe:
#!/bin/sh
#
# Re-encode video clips in MPEG transport stream (MPEG-TS) format applying
# some saturation and gamma correction.
#
# saturation: In range 0.0 to 3.0. The default value is "1".
# gamma_{r|g|b} In range 0.1 to 10.0. The default value is "1".
INPUT="$1"
OUTPUT="$INPUT.eq.ts"
EQ_FILTER="eq=saturation=0.88:gamma_r=0.917:gamma_g=1.007:gamma_b=1.297"
# Produces MPEG segments like the ones produced by the SJCAM SJ8Pro:
ffmpeg -i "$INPUT" \
-vf "$EQ_FILTER" \
-codec:v libx264 \
-preset veryslow -profile:v main -level:v 4.2 -pix_fmt yuvj420p \
-x264-params 'vbv-maxrate=38000:vbv_bufsize=20000:nal-hrd=vbr:force-cfr=1:keyint=8:bframes=0:scenecut=-1:ref=1' \
-keyint_min 8 -brand avc1 -f 3gp \
-bsf:v h264_mp4toannexb -f mpegts \
"$OUTPUT"
The gamma correction for the three RGB channels was determined with the GIMP, using the //Colors// => //Levels// => //Pick the gray point for all channels// tool. The use of MPEG-TS clips allowed the montage of the final video by just concatenating them.
===== AVC (x264) is better than ASP (xvid4) =====
See this page: **[[https://www.avidemux.org/admWiki/doku.php?id=general:common_myths|Common myths]]** to understand the differences between formats (standards) and codecs (pieces of software). Read also this simple page: **[[https://www.cyberlink.com/support/product-faq-content.do?id=1901|Difference between MPEG-4 AVC and MPEG-4 ASP]]**. See also the Wikipedia article about **[[wp>Advanced Video Coding]]**.
* **MPEG-4 Part 2 ASP** (Advanced Simple Profile)
* Support only 16x16 block size.
* Implemented by the Xvid library/codec.
* **MPEG-4 Part 10 AVC** (Advanced Video Coding)
* Support variable motion compensation block sizes.
* Implemented by the x264 library.
If you want to tweak with x264 codec options, here are some hints on the parameters meaning:
* **Preset**: Use the **slow** preset (or less) to achieve best compression ratio, at the expense of more time to encode.
* **Tuning**: Use the **film** option for real life scenes.
* **Profile**: The **High** profile is OK for high-definition television (e.g. 1280×720, or Blu-ray disc), //High 10// add support for 10 bits per sample, //High 444// up to 14 bits per sample (both for [[wp>High dynamic range|HDR]] videos). Do not use //Main//, which is for standard-definition TV, e.g. 720×576.
* **IDC Level**: Leave this parameter to **Auto**, setting it to higer values does not increase the video quality, but imposes higher constraints to the decoder. I.e. to decode a 1280×720@30 stream it is sufficient the 3.1 IDC level, to decode a 1920×1080@30 stream (max 20 Mbps) it is required the 4 IDC level (see [[wp>Advanced Video Coding]]).
====== More on ffmpeg Command Line ======
===== Suppress Some Output =====
Every **ffmpeg** invocation can be made **less verbose**, e.g. by suppressing all the messages **except the errors**:
ffmpeg -loglevel error ...
===== Getting Help on Command Line =====
**NOTICE**: Often there are **generic ffmpeg options** that produce the same effects of **options specific to the used codec**. As an example, the generic option
ffmpeg -i input.mp4 -g 8 ...
sets the **GOP** size (group of picture, i.e. the distance between one keyframe and the other). Using the x264 codec you can use a specific option, like this:
ffmpeg -i input.mp4 -c:v libx264 -x264-params keyint=8 ...
=== Full Help About ffmpeg Options ===
ffmpeg -h full
=== Help About a Specific Codec Options ===
How to **get help about options of an external encoder**. The **ffmpeg** executable must be compiled with support for that external library, in a Debian system you must install the appropriate packages, e.g. **ffmpeg** and **libx264-148** from [[http://www.deb-multimedia.org|Debian Multimedia]]:
ffmpeg -help encoder=libx264
that options can be used on the ffmpeg command line, after the **''%%-c:v libx264%%''** option.
=== More libx264 Options ===
Some options of the x264 library can be specified on the ffmpeg command line (see above). Many other options are read from system or user's configuration files (e.g. **''$HOME/.ffmpeg/x264-preset.ffpreset''**). That advanced options can be overridden on the ffmpeg command line using the **''%%-x264-params%%''** parameter. Example:
ffmpeg -i input.mp4 -c:v libx264 -profile main -x264-params 'keyint=8:bframes=0' output.mp4
To obtain the full list of x264 options you must execute the **x264** command line tool (provided by the **x264** Debian package). Be aware that there may be discrepancies between the versions of the libraries used; on our system **ffmpeg** is compiled against **libx264-148** (both packages installed from Debian Multimedia), instead the **x264** tool may be compiled against **libx264-142** if installed from Debian Main archive.
x264 --fullhelp
=== Help About a Specific Video Filter ===
ffmpeg has many video filter that can be applied. To get the available options of a specific filter, execute this command:
ffmpeg -help filter=scale
then you can pass the options on the command line, as the argument of the **''%%-vf%%''** video filter option:
ffmpeg -i input.mp4 -vf 'scale=1920:1080:flags=bicubic' output.mp4
as an alternative you can pass some options as native ffmpeg options:
ffmpeg -i input.mp4 -vf 'scale=1920:1080' -sws_flags bicubic output.mp4
===== Getting Video Info =====
To get quick info about an audio/video file, you can use the **mediainfo** tool, from the omonymous Debian package. Otherwise there is the **ffprobe** tool from the ''ffmpeg'' Debian package.
Show several info about audio/video stream in file. E.g. **codec_name**, **codec_time_base**, **width**, **height**, **avg_frame_rate**, **duration**, etc.
ffprobe -show_streams video.mp4
show one line of info per frame in CSV format:
ffprobe -show_frames -select_streams v -print_format csv video.mp4
the CSV format can be controlled by several options, e.g. if you want to print each field as a **key=val** pair, use:
ffprobe -show_frames -select_streams v -print_format csv=nokey=0 video.mp4
Among others, you can get data like:
^ key_frame | **1** or **0** if the frame is a **[[wp>Key frame]]** or not. |
^ pkt_pts | Packet **[[wp>Presentation timestamp|Presentation Time Stamp]]** in //time_base// units. |
^ pkt_pts_time | Packet Presentation Time Stamp in seconds. |
^ pkt_dts | Packet **Decoding Time Stamp** in //time_base// units. |
^ pkt_dts_time | Packet Decoding Time Stamp in seconds. |
^ pkt_duration | Packet duration in //time_base// units. |
^ pkt_duration_time | Packet duration in seconds. |
^ width | Width in pixel, e.g. 1920 |
^ height | Height in pixel, e.g. 1080 |
^ pix_fmt | e.g. yuvj420p. |
^ pict_type | **I**, **P** or **B** for //Intra// frame, //Predictive// frame and //Bidirectional// predictive frame. Indicates the type of [[wp>Video compression picture types]]. |
===== Extractig AAC Audio from MP4 File (or other format/container) =====
With this two commands we will extract AAC audio from an MP4 file, and then convert it into a 16 bit WAV file at 48 KHz:
ffmpeg -i video.mp4 -vn -c:a copy audio.m4a
ffmpeg -i audio.m4a -vn -c:a pcm_s16le -ar 48000 avaudio.wav
The **extension** used as destination file **does matter** for ''ffmpeg'', if you use a wrong one you may get the error message //Unable to find a suitable output format//.
You should use the **mediainfo** tool (from the omonymous Debian package) to inspect the the video file and discover the audio format, then use the proper file extension. E.g. if the source file has an audio stream in **Opus** format, you should use:
ffmpeg -i video.mkv -vn -c:a copy audio.opus
**WARNING!** If you plan to use the track into Audacity (or something that converts it into uncompressed format), **check the duration** of the track before and after the conversion. If you see some mismatch you can use the following recipe to fix timestamp gaps in the source:
ffmpeg -i audio.m4a -af aresample=async=1 audio.wav
==== Stabilizzazione video ====
Come stabilizzare un video tremolante. La procedura ovviamente sacrifica una parte del video, tagliando i bordi. Vedere il post **[[https://www.epifocal.net/blog/video-stabilization-with-ffmpeg|Video Stabilization with FFmpeg]]**.
L'operazione si compie in due passaggi, il primo calcola i **vettori di stabilizzazione** e li salva in un file:
ffmpeg -i input.mp4 \
-vf vidstabdetect=stepsize=6:shakiness=8:accuracy=9:result=stab_vect.trf -f null -
il secondo passaggio applica la correzione:
ffmpeg -i input.mp4 \
-vf vidstabtransform=input=stab_vect.trf:zoom=1:smoothing=30,unsharp=5:5:0.8:3:3:0.4 \
-vcode c libx264 -preset slow -tune film -crf 18 -acodec copy outout.mp4
I parametri utilizzati nell'esempio sono molto "aggressivi", provare a diminuire la **shakiness** (ad esempio usando valore 3 o 4) e diminuire anche lo **zoom** e lo **smoothing**.
Un test con un video molto mosso (telecamera impugnata a mano su motocicletta in movimento) con **zoom=1** e **smoothing=30** ha ridotto il film a circa il 77% dell'originale sulle due dimensioni. Dei 1920 pixel originali di larghezza ne sono stati estrapolati circa 1480 (il filmato viene comunque scalato per mantenere la dimensione originale). Impostando lo **zoom=0.5** si sono recuperati circa 15 pixel lineari (riduzione al 78% dell'originale).
===== Aggiunta sottotitoli =====
Se si ha un file con i sottotitoli per un video, è possibile fare il muxing:
ffmpeg -i movie.mkv -i movie.sub -c copy \
-sub_charenc UTF-8 -c:s srt -metadata:s:s:0 language=eng \
movie_sub.mkv
====== Deinterlace ======
We can use the video filter named **yadif** (//yet another deinterlacing filter//). In this example the result was encoded in MPEG-4 AVC using the libx264 library, forcing one keyframe every 8 frames:
ffmpeg -i input-video.mkv -codec:a copy -vf yadif -codec:v libx264 -preset slow \
-x264-params 'force-cfr=1:keyint=8:bframes=0:ref=1' \
output-video.mkv
====== Problem in MKV Remux ======
It seems there is a bug in ffmpeg **[[https://trac.ffmpeg.org/ticket/6037|#6037 mkv muxing not broken]]**: muxing two working files into a mkv produces a broken file: seeking around can break (mute) audio. I experienced this bug (with ffmpeg 4.1.6) trying to mux one mkv file containing one audio and one subtitle streams to another mkv file conaining video and audio. The resulting file did not play good in mplayer: seeking into the file caused audio or vido to stop playing.
This was the first try command line:
# The resulting video is broken.
ffmpeg -i input_file1.mkv -i input_file2.mkv \
-map '0:v:0' -map '0:a:0' \
-map '1:a:0' -map '1:s:0' \
-codec:v copy -codec:a copy -codec:s copy \
output_file.mkv
The workaround was to extract each individual stream, and mux then together:
ffmpeg -i input_file1.mkv -map 0:v:0 -codec:v copy input-v_env.mkv
ffmpeg -i input_file1.mkv -map 0:a:0 -codec:a copy input-a_ita.mkv
ffmpeg -i input_file2.mkv -map 0:a:0 -codec:a copy input-a_eng.mkv
ffmpeg -i input_file2.mkv -map 0:s:0 -codec:s copy input-s_eng.mkv
ffmpeg \
-i input-v_env.mkv \
-i input-a_ita.mkv \
-i input-a_eng.mkv \
-i input-s_eng.mkv \
-codec:v copy -codec:a copy -codec:s copy \
-map '0' -map '1' -map '2' -map '3' \
output_file.mkv
====== ffmpeg: leggere la sequenza di VOB da un DVD ======
Nella directory **VIDEO_TS** di un DVD la traccia principale è normalmente suddivisa in file numerati sequenzialmente, ad esempio: ''VTS_01_0.VOB'', ''VTS_01_1.VOB'', ...
In teoria è sufficiente concatenare i file in un solo file destinazione e quindi trattarlo come un normale file audio/video. Tuttavia è possibile indicare i singoli file come input senza la necessità di occupare ulteriore spazio disco con questa sintassi:
SOURCE="concat:VTS_01_1.VOB|VTS_01_2.VOB|VTS_01_3.VOB|VTS_01_4.VOB|VTS_01_5.VOB"
ffmpeg -i "$SOURCE" ...
====== ffmpeg: impostare un ritardo sui sottotitoli durante il muxing ======
Se un flusso di sottotitoli (ad esempio nel formato Picture based DVD) non indica correttamente l'offset iniziale di riproduzione è possibile dire ad ffmpeg di impostarlo opportunamente in fase di muxing. In questo esempio il primo sottotitolo appare a 44.5 secondi:
ffmpeg -i video-stream.mkv -i audio-stream.mkv -itsoffset 44.5 -i subtitles-stream.mkv ...
In generale dovrebbe essere possibile scoprire l'offset quando ffmpeg legge l'intero stream, al momento in cui trova il prmio frame dei subtitles mostra qualcosa del genere sulla console:
[mpeg @ 0x55f98bb2c6c0] New subtitle stream 0:7 at pos:14755854 and DTS:44.5s
====== Parameters for final rendering ======
See the page **[[ffmpeg_final_rendering]]**.
====== Doppiaggio audio con Ardour ======
Vedere la pagina dedicata: **[[ardour_dubbing]]**.