How do I set the colorspace to bt.709 for h.264 encoding

I have a video with these properties

[streams.stream.0]
index=0
codec_name=h264
codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
profile=Constrained Baseline
codec_type=video
codec_time_base=1001/60000
codec_tag_string=avc1
codec_tag=0x31637661
width=1920
height=1080
coded_width=1920
coded_height=1088
has_b_frames=0
sample_aspect_ratio=N/A
display_aspect_ratio=N/A
pix_fmt=yuvj420p
level=50
color_range=pc
color_space=bt709
color_transfer=bt709
color_primaries=bt709
chroma_location=left
field_order=unknown
timecode=N/A
refs=1
is_avc=true
nal_length_size=4
id=N/A
r_frame_rate=30000/1001
avg_frame_rate=30000/1001
time_base=1/30000
start_pts=0
start_time=0:00:00.000000
duration_ts=10130120
duration=0:05:37.670667
bit_rate=45.051380 Mbit/s
max_bit_rate=N/A
bits_per_raw_sample=8
nb_frames=10120
nb_read_frames=N/A
nb_read_packets=N/A

I am trying to encoding it using h264_amf into a mov container

When I encoding it I would like it to retain the bt.709 colorspace
But my results have the colorspace set to unknown along with the color trc and primaries set to unknown

I read in another post to use this on the Other tab
colorspace=1
color_trc=1
color_primaries=1

But it still sets it to unknown
I am practicing on this file because I plan to stitch this file and two others together along with doing some editing but I would like to get the encoding settings to what I want on a smaller file before I encode the final project.

Here is my list of ‘other’ settings
pix_fmt=yuvj420p
mlt_image_format=rgb2
color_range=pc
colorspace=1
color_trc=1
color_primaries=1

So my question is can I encode this using h264_amf in a mov container and retain the bt.709 colorspace?

I don’t know the “official” answer, but I can reproduce the problem and have doubts about there being a direct solution.

The MOV container format does not have a flag to indicate color range. It assumes video is MPEG/TV range. The way to get around that is to use the yuvj420p pixel format as you’re doing, which indirectly implies JPEG/PC color range. However, many hardware encoders don’t support yuvj420p. Their circuitry is hardwired for yuv420p with MPEG/TV range. If you inspect the pix_fmt of the output file, it may have silently switched to yuv420p along with color_range=unknown. This becomes a circular problem.

As for alternatives, the MP4 and Matroska containers do have color range flag support. Using libx264 with those containers, color_trc=bt709 and color_primaries=bt709 can be added to the Other box and the export will include them. And colorspace is always included with a libx264 export.

As for colorspace, it is baked into the video mode of the project and isn’t something to configure from the Other tab. If you select from the menu Settings > Video Mode > Custom > Add, there is an option to set the color space of the video mode. The HD-and-up presets are already set to bt709. This is what determines the colorspace of the exported file. This metadata doesn’t get exported with AMF or QSV or possibly other hardware encoders because hardware takes over and does an incomplete job. I’m not sure how to override that.

So, those are the constraints. The good news is that if these clips are stitched together into a final export, then their metadata isn’t critical because it can be set in the Shotcut UI or ffmpeg CLI to the correct values and then forced or updated on the final file. Might be a little work, but you would keep your AMF export speed.

colorspace and color_trc are set automatically (by MLT, not shown in UI or XML) according to the Shotcut Video Mode. color_range defaults to mpeg/tv and available for override. Of course, it also depends upon support by the muxing format and codec per what Austin wrote.

Thank you for the detailed responses. I appreciate it. I switched to Matroska and as you said the color_trc and color_primaries were set to bt709 once I did this. I still have an unknown colorspace however.

I feel like I had the video mode setup correctly per your instructions but maybe I maybe I didn’t completely understand.

Here is the info for the new output I have

Other Settings
pix_fmt=yuvj420p
mlt_image_format=rgb2
color_range=pc
colorspace=1
color_trc=1
color_primaries=1

Video Mode

I checked the video mode config “MyVideoMode” and it is set to ITU-R BT.709

Output File Info
[streams.stream.0]
index=0
codec_name=h264
codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
profile=Main
codec_type=video
codec_time_base=1001/60000
codec_tag_string=[0][0][0][0]
codec_tag=0x0000
width=1920
height=1080
coded_width=1920
coded_height=1088
has_b_frames=0
sample_aspect_ratio=1:1
display_aspect_ratio=16:9
pix_fmt=yuvj420p
level=50
color_range=pc
color_space=unknown
color_transfer=bt709
color_primaries=bt709
chroma_location=left
field_order=progressive
timecode=N/A
refs=1
is_avc=true
nal_length_size=4
id=N/A
r_frame_rate=30000/1001
avg_frame_rate=30000/1001
time_base=1/1000
start_pts=0
start_time=0:00:00.000000
duration_ts=N/A
duration=N/A
bit_rate=N/A
max_bit_rate=N/A
bits_per_raw_sample=8
nb_frames=N/A
nb_read_frames=N/A
nb_read_packets=N/A

I thought maybe it had to do with the hardware encoder [h264_amf] so I tried turning that off and using libx264 but it had the same results.

rgb2 is an invalid value. I think you want rgb24

colorspace=1

This name is also used by MLT, but this value is invalid in the context of MLT. As I said before, MLT manages this value on FFmpeg, so you should not set it here.

color_trc=1

color_trc is also managed by MLT based on colorspace, but you can override it. No need to in the case of BT.709, however.

color_primaries=1

This one is not managed by MLT.

So, putting all this together, use any number of Video Modes that use BT.709, and add only the following in Other:

pix_fmt=yuvj420p
mlt_image_format=rgb24
color_primaries=bt709

and you get in output of ffprobe;

color_range=pc
color_space=bt709
color_transfer=bt709
color_primaries=bt709

For the next version 20.06, I added automatic set of color_primaries within MLT based on colorspace. Of course, it can be overridden using color_primaries.

2 Likes

Not sure what MLT stands for but I understand what you mean now. It is handled behind the scenes in shotcut based on the colorspace set in the video mode and thus I don’t need to set the attributes in Other.

I tried
pix_fmt=yuvj420p
mlt_image_format=rgb24
color_primaries=bt709

and it gave me output that looked like this
image

So I added color_range back
color_range=pc
pix_fmt=yuvj420p
mlt_image_format=rgb24
color_primaries=bt709

And once I did that it gave me this:
pix_fmt=yuvj420p
level=50
color_range=pc
color_space=bt709
color_transfer=bt709
color_primaries=bt709

Which is my desired output.
Thank you for the help.

Should these same settings work for the MP4 container?

pix_fmt=yuvj420p
mlt_image_format=rgb24
color_primaries=bt709

They work for mkv
Work as in the give the output of
color_space=bt709
color_transfer=bt709
color_primaries=bt709

But when I tried them with the MP4 container I get
color_space=unknown
color_transfer=unknown
color_primaries=unknown

How can I determine what flags work with what containers?

It works for me:

How can I determine what flags work with what containers?

Read the FFmpeg source code or sometimes on its wiki.

MLT (Media Lovin’ Toolkit) is the open source multimedia framework developed by Dan that is the basis for Shotcut.

This is a common problem if using a hardware encoder. Try it with libx264. I’m not sure how to override these values when using hardware, except to manually rewrap the file with ffmpeg after it is exported.

@shotcut Thank you for quick response and trying it out locally. I was using the hardware encoder to get the speed boost. Once I changed it to libx264 it worked correctly.

@Elusien Thank you for clearing up MLT for me.

@Austin Thank you for the tip. That is exactly what the issue was. I was using h264_amf and once I changed it to libx264 it work like @shotcut said. I will use libx264 I just wish it didn’t take the process time from 2 mins (with h264_amf) to 4 mins for a small file.

Video hardware encoders are designed for speed of encoding, at the expense of file-size (they usually produce a much bigger file) and quality. they are perfect for streaming, but not for producing quality videos.

This topic was automatically closed after 90 days. New replies are no longer allowed.