1

I want to encode a video that will be compatible with videos created by my phone. That way I can mux the new video with the original without re-encoding the original video. I use FFmpeg with the libx264 encoder. The following are the MediaInfo specs of the original video created by my phone:

ID                                       : 1
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : Baseline@L3.1
Format settings                          : 1 Ref Frames
Format settings, CABAC                   : No
Format settings, Reference frames        : 1 frame
Format settings, GOP                     : M=1, N=30
Codec ID                                 : avc1
Codec ID/Info                            : Advanced Video Coding
Duration                                 : 52 s 369 ms
Bit rate                                 : 10.0 Mb/s
Width                                    : 1 280 pixels
Height                                   : 720 pixels
Display aspect ratio                     : 16:9
Frame rate mode                          : Variable
Frame rate                               : 30.000 FPS
Minimum frame rate                       : 29.625 FPS
Maximum frame rate                       : 30.405 FPS
Standard                                 : NTSC
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Progressive
Bits/(Pixel*Frame)                       : 0.362
Stream size                              : 62.4 MiB (98%)
Title                                    : VideoHandle
Language                                 : English
Encoded date                             : UTC 2020-10-27 19:43:55
Tagged date                              : UTC 2020-10-27 19:43:55
Color range                              : Limited
Color primaries                          : BT.709
Transfer characteristics                 : BT.709
transfer_characteristics_Original        : BT.601
Matrix coefficients                      : BT.709
mdhd_Duration                            : 52369
Codec configuration box                  : avcC

So far, I have figured out the following, which I think has gotten me close:

ffmpeg -i in.mp4 -c:v libx264 -profile:v baseline -level:v 3.1 -refs 1 \
  -vsync 2 -filter:v scale="-1:720",pad="1280:720:720/2+ow/2",format="yuv420p" \
  -x264-params keyint="30":scenecut="0" -c:a copy out.mp4

I'm having trouble setting frame rate. It should be variable @ 30 fps. I found this question in regards to variable frame rate. But it has no answer. Setting -minrate & -maxrate does not help. The output is constant frame rate @ 30 FPS. Parameter examples follow.

  • Outputs constant rate @ 30 fps:
    -vsync 2 -r 30 -minrate 29.625 -maxrate 30.405
    
  • Outputs variable rate @ 29.970:
    -vsync 2 -r 30.405
    

I also believe that I should be using -crf or -qp, but am not sure of the correct value(s).

Edit:

The command shown above results in the following specs:

ID                                       : 1
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : Baseline@L3.1
Format settings                          : 1 Ref Frames
Format settings, CABAC                   : No
Format settings, Reference frames        : 1 frame
Format settings, GOP                     : M=1, N=30
Codec ID                                 : avc1
Codec ID/Info                            : Advanced Video Coding
Duration                                 : 8 s 700 ms
Duration_FirstFrame                      : 33 ms
Bit rate                                 : 2 606 kb/s
Width                                    : 1 280 pixels
Height                                   : 720 pixels
Display aspect ratio                     : 16:9
Frame rate mode                          : Constant
Frame rate                               : 30.000 FPS
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Progressive
Bits/(Pixel*Frame)                       : 0.094
Stream size                              : 2.69 MiB (95%)
Title                                    : VideoHandle
Writing library                          : x264 core 160
Encoding settings                        : cabac=0 / ref=1 / deblock=1:0:0 / analyse=0x1:0x111 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=0 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=6 / lookahead_threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=0 / weightp=0 / keyint=30 / keyint_min=3 / scenecut=0 / intra_refresh=0 / rc_lookahead=30 / rc=crf / mbtree=1 / crf=23.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00
Language                                 : English
Codec configuration box                  : avcC

Is there anything else shown here that isn't compatible with the original video?


Sources that helped me:

Edit (2020-11-6 23:40 UTC):

After reading Gyan's answer, I used the -video_track_timescale parameter to set a tbn value to match the original video. But the concatenated video still does not display correctly. Did I miss something that should be matching? I'm looking over the ffprobe output now.

Original video:

$ ffprobe -hide_banner -i VID_20201027_124301.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'VID_20201027_124301.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2020-10-27T19:43:55.000000Z
    location        : +42.5418-122.5700/
    location-eng    : +42.5418-122.5700/
    com.android.version: 7.1.2
  Duration: 00:00:52.40, start: 0.000000, bitrate: 10187 kb/s
    Stream #0:0(eng): Video: h264 (Baseline) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1280x720, 10002 kb/s, SAR 1:1 DAR 16:9, 30 fps, 30 tbr, 90k tbn, 180k tbc (default)
    Metadata:
      creation_time   : 2020-10-27T19:43:55.000000Z
      handler_name    : VideoHandle
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      creation_time   : 2020-10-27T19:43:55.000000Z
      handler_name    : SoundHandle

FFmpeg encoded video:

$ ffprobe -hide_banner -i VID_20201027_124914-encoded.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'VID_20201027_124914-encoded.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.29.100
  Duration: 00:00:08.70, start: 0.000000, bitrate: 2732 kb/s
    Stream #0:0(eng): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 2596 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandle
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : SoundHandle

Edit (2020-11-7 00:05 UTC):

Did some more testing & found that when I concatenate the video using FFmpeg, it works. But if I concatenate using a different muxer, like Avidemux or MKVToolNix, it does not. I think this question has been answered by Gyan, but I'm going to keep it open just a little longer to see if there is any input on why the video does not work with the other muxers as I prefer to use those.

Ultimate ffmpeg parameters used:

ffmpeg -i in.mp4 -c:v libx264 -profile:v baseline -level:v 3.1 \
  -refs 1 -r 30 -video_track_timescale 90k \
  -filter:v scale="-1:720",pad="1280:720:720/2+ow/2",format="yuv420p" \
  -x264-params keyint="30":scenecut="0" -c:a copy out.mp4

the keyint & scenecut params of -x264-params & framerate aren't required

Edit:

Created question about concatenation not working with Avidemux & MKVToolNix here.

2

To concatenate multiple files for expected playback in common players, following properties need to match for

video: codec, codec profile, codec level, resolution, reference count, pixel format, timebase/timescale.
audio: codec, codec profile, channel count & layout, sample format and sampling rate.

Advanced players can tolerate mid-stream changes in some of the above parameters.

Mediainfo won't show you timescale, it's the tbn value as shown by ffmpeg for the stream. Framerates need not match nor be constant for any given constituent stream. GOP size or keyframe cadence need not match. Neither need bitrate value or mode (CRF, VBR..etc) match. minrate and maxrate clamp bitrate, not framerate.

6
  • Okay, ffmpeg shows 30 fps, 30 tbr, 90k tbn, 180k tbc for the video produced by my phone. I used -video_track_timescale 90k option & the output video shows 29.89 fps, 30 tbr, 90k tbn, 60 tbc. But concatenated video still not displaying correctly in VLC nor MPlayer. Everything else you outlined matches. Does tbc need to match as well? Nov 6 '20 at 23:23
  • I updated my question to show the ffprobe output of the two videos. Nov 6 '20 at 23:42
  • New info: After following your answer, concatenating with FFmpeg works. Thank you. However, if I use a different utility to mux, such as Avidemux or MKVToolNix, the concatenated video does not display correctly. Any idea of why this might be? Nov 7 '20 at 0:04
  • Created new question for this. Nov 7 '20 at 1:02
  • 1
    Strictly speaking, to avoid failing with hardware-constrained decoders, the level and profile of further files should not exceed those of the first file.
    – Gyan
    Mar 17 at 4:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.