Skip to content

Instantly share code, notes, and snippets.

@aphex3k
Last active September 1, 2022 09:29
Show Gist options
  • Save aphex3k/61d47728aef203f11355d122dd157164 to your computer and use it in GitHub Desktop.
Save aphex3k/61d47728aef203f11355d122dd157164 to your computer and use it in GitHub Desktop.
Transcoding MPEG2 TS to H.264 MP4

Transcoding MPEG2 TS to H.264 MP4

The goal is to transcode a DVR recording containing one video source in mpeg2 format, any number (typically 2-3) of audio sources in ac-3 format and maybe a subtitle source all together in a transport stream container. In addition the video stream might be interlaced.

The target is a video file playable natively on modern iOS and Android devices using their platforms native and hardware supported playback capabilities.

Target file container and formats

The target file container and supported stream formats are listed below to ensure very good playback compatibility on modern devices and platforms.

  • MP4/M4V container format
  • AC-3 audio format
  • H.264 video format (profile: high, level: 4.2)

Hardware encoding pipeline using NVidia CUDA

The system is equipped with an RTX 2080 boasting powerfull hardware video encoding capabilities. The final file size for a same quality video might be a little higher than a pure software/CPU pipeline, but the tradoff is big savings in absolute time spent filtering and encoding the video!

All right, here is the final command: (TLDR;)

ffmpeg -threads 0 -hide_banner -y -hwaccel cuvid -c:v mpeg2_cuvid -i "${inFile}" -c:v h264_nvenc -vf yadif_cuda=0:-1:1,scale_npp=format=yuv420p,hwdownload,format=yuv420p,decimate -preset hq -refs 4 -bf:v 2 -profile:v high -level 4.2 -qmin 19 -qmax 24 -maxrate 6M -bufsize 12M -map 0:0 -map 0:m:language:eng -c:a copy -map 0:s? -c:s copy -movflags +faststart

Let's take the plethora of arguments apart piece by piece.

Command line arguments

-threads 0 the host is a multicore-CPU system and few tasks in the pipeline are still threadable although the brunt of the work happens during encoding on the GPU, this enables use of all available cores

-hide_banner this keeps the console log cleaner

-y the script will ultimately run on a headless system and this overwrites any existing output file by default

-hwaccel cuvid this tells ffmpeg to enable CUDA for the pipeline

-c:v mpeg2_cuvid this instructs the decoder to use the GPU for any decoding of the input file

-c:v h264_nvenc this instructs the encoder to use the GPI for any encoding of the ouput file

-vf yadif_cuda=0:-1:1 the input file might be encode progressive or interlaced. In the latter case this filter will deinterlace it.

scale_npp=format=yuv420p,hwdownload,format=yuv420p this part of the filter pipeline will convert the pixelformat of the encoded frames to yuv420p (instead of cuda or nv12)

-preset slow CUDA encoding preset: High Quality 2-Pass

-refs 4 Use 4 reference frames

-bf:v 2 Use 2 B-Frames

-profile:v high -level 4.2 H.264 encoding profile HIGH, Level 4.2

-qmin 18 -qmax 22 variable bitrate encoding, target visual fidelity will be between CQP 18 and CQP 22

-maxrate 6M -bufsize 12M maximum encoding bitrate of 6MBit/s leave enough bits to encode 720p as well as 1080p proper

-map 0:0 -map 0:s? -c:s copy stream mapping: include the first stream (0:0, typically the first video stream of a file) and all subtitles if present (0:s?) and do not transcode subtitle streams to a different format

-map 0:0 -map 0:m:language:eng -c:a copy include the audio stream that maps to the english language and copy it instead of transcoding

-movflags +faststart include a second pass moving the final moov atoms to the beginning of the file to increase fidelity when streaming the output file from a non-local drive or remote stream

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment