FFMPEG Commands for Vision Pro
FFmpeg and Apple Device
Hi, I’m building a video platform for an Apple device. FFmpeg is incredibly useful for encoding videos, but we need to be cautious when preparing videos for playback on an Apple device like the Vision Pro.
FFmpeg Commands
I’ll share some commands for video encoding.
Basic Encoding
Let’s start with a basic command:
ffmpeg -i input.mp4 -c:v libx265 -b:v 200M -profile:v main -tag:v hvc1 -map_metadata 0 -c:a copy output.mp4
Okay, I'll explain this command.
-
-i
option- Specifies the input file. The
-i
flag tells FFmpeg which file to process. In this case,input.mp4
is the source video file that will be converted or manipulated.
- Specifies the input file. The
-
-c:v
option-
c:v
stands for "codec: video" and defines the encoder to use for the video stream. - We can choose an encoder. Typically, we use either
libx265
orhevc_videotoolbox
:-
libx265
(aka x265) is the HEVC encoder produced by MulticoreWare. It is open-source and uses software encoding. This means it takes more time but provides higher quality compared to hardware encoding. -
hevc_videotoolbox
(aka VideoToolbox) is the HEVC encoder produced by Apple. It uses hardware encoding with the GPU, making it much faster than software encoding. However, the quality is lower at the same bitrate.
-
-
-
-b:v
option-
b:v
stands for "bitrate: video" and specifies the target bitrate for the video stream. - If you wanna constraints the bit rate, I reccomend the below article. I often use libx265 encoder not hevc_videotoolbox when I wanna achieve that. But official workaround it the following.
-
-
-profile:v
option-
profile:v
specifies the encoding profile for the video codec. - The
main
profile is a common profile in H.265. It supports 8-bit color depth. - If you want to encode with 10-bit color depth, you need to set the
main10
profile.
-
-
-tag:v
option-
tag:v
sets a codec tag for the video stream in the output container. - To ensure compatibility with Apple devices, you need to set this to
hvc1
.
-
-
map_metadata
option-
map_metadata
controls how metadata (e.g., title, author, creation date) is handled. -
0
refers to the first input file (in this case, input.mp4). This tells FFmpeg to copy all metadata from the input file to the output file (output.mp4).
-
-
c:a
option-
c:a
stands for "codec: audio" and specifies the audio codec. - copy instructs FFmpeg to pass the audio stream from input.mp4 to output.mp4 unchanged, without re-encoding.
-
Check video details
You can check video details like color primaries, color transfer and so on.
ffprobe -v error -show_format -show_streams input.mp4
If you wanna restrict output to the specific info, you can use grep command after using ffprobe command like the below.
ffprobe -v error -show_format -show_streams input.mp4 | grep -E "^pix_fmt|^bit_rate|^r_frame_rate|^color_space|^color_transfer|^color_primaries|^profile"
Change Frame rate and Resolution
If you wanna change FPS and Resolution for the video, you can use the following command.
ffmpeg -i input.mp4 -vf fps=<frame rate>,scale=<witdth>:<height> -c:v libx265 -b:v 200M -profile:v main -tag:v hvc1 -map_metadata 0 -c:a copy output.mp4
Video cut with specific time
If you wanna cut the video with specific time, you can use the following commands.
Cut the video from the beggining.
ffmpeg -i input.mp4 -t <seconds> -c copy output.mp4
Cut the video from the specific time.
ffmpeg -i input.mp4 -ss <00:00:00> -to <00:00:40> -c copy output.mp4
Video divide to right and left
ffmpeg -i input.mp4 -vf "crop=iw/2:ih:0:0" -c:v libx265 -b:v 200M -profile:v main -tag:v hvc1 -map_metadata 0 -c:a copy output.mp4
Zero B-frame
Sometimes we wanna control GOP for HEVC. And the following command generates the video with Zero B-frame.
ffmpeg -i input.mp4 -c:v libx265 -b:v 200M -profile:v main -tag:v hvc1 -map_metadata 0 -x265-params "bframes=0" -c:a copy output.mp4
If you are not familiar with GOP and B-frame, you can check my another article for HEVC.
Why I wrote this command? Because sometimes custom decoder is built for IDR and P-frame. So if you try to play the HEVC video with such a decoder, it leads to fail for decoding.
Set IDR interval
If you wanna set IDR frame every 90 frames, you can use -g 90
option.
ffmpeg -i input.mp4 -c:v libx265 -b:v 200M -profile:v main -tag:v hvc1 -map_metadata 0 -g 90 -x265-params "bframes=0:open-gop=0" -c:a copy output.mp4
And do not forget to set open-gop=0
, if you wanna play on Apple Device. Apple Device does not support open GOP.
What is Open and Closed GOPs? Please check this link.
Divide into multi tiles
If you wanna divide your HEVC video into multi tiles, you can use the following command.
ffmpeg -i input.mp4 -c:v libx265 -b:v 200M -profile:v main -tag:v hvc1 -map_metadata 0 -x265-params "tiles=3x3" -c:a copy output.mp4
What is tile? Please check my another article. It's really important in terms of decoding speed on the edge device.
Crop SBS video from the center position of each eye
If you have a Side By Side video and want to crop it, you need to divide it for left and right first. After that, you can crop each frame. And be careful if you divide frame, you need to set color property with "-x265-params".
The following example shows the situation that you want to crop 7200x7200 resolution frame (for each eye) to 6600x6000.
SDR
ffmpeg -i input.mp4 -filter_complex "[0:v]crop=7200:7200:0:0[left_full];[0:v]crop=7200:7200:7200:0[right_full];[left_full]crop=6600:6000:300:600[left];[right_full]crop=6600:6000:300:600[right];[left][right]hstack=inputs=2[stacked]" -map "[stacked]" -map 0:a -c:v libx265 -b:v 200M -profile:v main -x265-params "colorprim=bt709:transfer=bt709:colormatrix=bt709" -tag:v hvc1 -map_metadata 0 -c:a copy output.mp4
HDR
ffmpeg -i input.mp4 -filter_complex "[0:v]crop=7200:7200:0:0[left_full];[0:v]crop=7200:7200:7200:0[right_full];[left_full]crop=6600:6000:300:600[left];[right_full]crop=6600:6000:300:600[right];[left][right]hstack=inputs=2[stacked]" -map "[stacked]" -map 0:a -c:v libx265 -b:v 200M -profile:v main10 -x265-params "colorprim=smpte432:transfer=smpte2084:colormatrix=bt709" -tag:v hvc1 -map_metadata 0 -c:a copy output.mp4
Discussion