stream-labs / obs-studio-node

libOBS (OBS Studio) for Node.Js, Electron and similar tools
GNU General Public License v2.0
606 stars 99 forks source link

amd_amf_h264 not configured in simple recording mode #1320

Closed aza547 closed 11 months ago

aza547 commented 1 year ago

Hi,

When when trying to use the SimpleRecordingFactory with the amd_amf_h264 encoder, it crashes (log attached).

It looks like that's because UpdateRecordingSettings_crf does not apply any configuration for this encoder.

The snippet below shows what looks like an attempt to:

else if (id.compare(SIMPLE_ENCODER_AMD) == 0 || id.compare(SIMPLE_ENCODER_AMD_HEVC) == 0 || id.compare(ADVANCED_ENCODER_AMD) == 0) {
  settings = UpdateRecordingSettings_amd_cqp(CalcCRF(crf));
}

But amd_amf_h264 isn't included in the string comparisons.

#define SIMPLE_ENCODER_AMD "amd"
#define SIMPLE_ENCODER_AMD_HEVC "amd_hevc"
...
#define ADVANCED_ENCODER_AMD "h264_texture_amf"

There are similar branches for (obs_x264, nvenc... etc.) encoders that work fine as far as I can tell.

Thanks. 2023-06-19 15-07-45.txt

avoitenko-logitech commented 1 year ago

@aza547 Hi. Could you please drop an example of how you are trying to use obs-studio-node if you have any. As log you posted is pretty concise I assume that you have some small chunk of code.

aza547 commented 1 year ago

Hi - thanks for the response, an example is in a branch here. My application does some automated recording, cutting and labelling of gameplay based on a log file.

I was investigating using the SimpleRecordingFactory rather than the AdvancedRecordingFactory as I'm not an expert in encoders and while the AdvancedRecordingFactory seems to work fine for me, it seemed a better approach to use the SimpleRecordingFactory and have encoder configuration automatically applied rather than have to apply it myself, given I'll probably get things wrong, they will vary across GPUs and I generally just lack the knowledge to be confident in config I'm applying.

That works fine on the branch I linked above for the obs_x264 encoder which I found quite promising, but I have an AMD card and trying to use the SimpleRecordingFactory for me with the AMD encoder causes the crash shown above. I guess what I'm really after here is a sensible method to apply encoder settings that doesn't rely on me guessing them, which looks like the SimpleRecordingFactory is really close to providing, with just perhaps a few string comparison tweaks to the code I linked in my initial post.

avoitenko-logitech commented 1 year ago

@aza547 in your project of wow recorder you have the following function:

  /**
   * Return an array of all the encoders available to OBS.
   */
  public getAvailableEncoders() {
    console.info('[Recorder] Getting available encoders');

    if (!this.obsInitialized) {
      throw new Error('[Recorder] OBS not initialized');
    }

    const encoders = osn.VideoEncoderFactory.types();
    console.info('[Recorder]', encoders);

    return encoders;
  }

and this function outputs to the console directly. For example its output on my machine looks like:

14:59:33.831 > [Recorder] Getting available encoders
14:59:33.831 > [Recorder] [
  'ffmpeg_svt_av1',
  'ffmpeg_aom_av1',
  'jim_nvenc',
  'jim_hevc_nvenc',
  'ffmpeg_nvenc',
  'ffmpeg_hevc_nvenc',
  'obs_qsv11_soft',
  'obs_qsv11',
  'obs_x264'
]

Could you please post output from your machine from the branch simple-rec-mode

avoitenko-logitech commented 1 year ago

The code above executes when you open scene editor.

aza547 commented 1 year ago

See below - thanks.

[2023-07-08 10:17:13.877] [info] [Recorder] Getting available encoders [2023-07-08 10:17:13.877] [info] [Recorder] [ 'amd_amf_h264', 'amd_amf_h265', 'ffmpeg_svt_av1', 'ffmpeg_aom_av1', 'h264_texture_amf', 'h264_fallback_amf', 'h265_texture_amf', 'h265_fallback_amf', 'obs_x264' ]

avoitenko-logitech commented 1 year ago

Hi @aza547. Hope you are doing great. I'm exploring OBS code and it seems like encoder name amd_amf_h264 and some others are reserved for internal use only.

Have you tried values like h264_texture_amf or even just amd? I think it might solve your problem.

Here are some details. In file UI\window-basic-settings-stream.cpp of OBS project i see

    if (service_supports_encoder(vcodecs, "h264_texture_amf"))
        ui->simpleOutStrEncoder->addItem(
            ENCODER_STR("Hardware.AMD.H264"),
            QString(SIMPLE_ENCODER_AMD));

And ENCODER_STR("Hardware.AMD.H264"), is displayed in the UI as Hardware (AMD, H.264) in en-US locale. Moreover, there are only 3 strings that have AMD prefix:

Basic.Settings.Output.Simple.Encoder.Hardware.AMD.H264="Hardware (AMD, H.264)"
Basic.Settings.Output.Simple.Encoder.Hardware.AMD.HEVC="Hardware (AMD, HEVC)"
Basic.Settings.Output.Simple.Encoder.Hardware.AMD.AV1="Hardware (AMD, AV1)"

And this also corresponds to the following defines in UI\window-basic-main.hpp

#define SIMPLE_ENCODER_AMD "amd"
#define SIMPLE_ENCODER_AMD_HEVC "amd_hevc"
#define SIMPLE_ENCODER_AMD_AV1 "amd_av1"

So I make conclusion that amd and h264_texture_amf should map internally to the desired amd_amf_h264 encoder.

aza547 commented 1 year ago

Hi @avoitenko-logitech :) Thanks again for the response. I'm well, hope you are also!

I did try these upfront before I originally reported the issue (I saw these strings in the OSN code so figured I'd give them a go).

IIRC the "AMD" encoder caused an error and the "h264_texture_amf" worked but didn't produce good results quality wise.

I've retried to record the behaviour.

Here's the OBS log for attempting to use "amd": 2023-07-15 12-41-23.txt

I suspect the interesting bit is: [000:00:00:02.836.822.400][13880][Error] Encoder ID 'amd' not found

That fits with "amd" not being returned in the list of allowed encoders.

The logs from the "h264_texture_amf " test: WarcraftRecorder-2023-07-15.log 2023-07-15 12-45-07.txt

The bit I think is interesting is from the encoder settings in the first log:

[2023-07-15 12:45:09.691] [info]  Video encoder settings: {
  bitrate: 2500,
  cqp: 20,
  preset: 'quality',
  profile: 'high',
  rate_control: 'CBR'
}

This bitrate seems too low despite the HigherQuality preset. The output video as a result is very pixelated, hopefully clear from the below image where left is the recording and right is the preview.

image

So perhaps this is the correct setting to use, but it seems it's not getting configured sensibly by the SimpleRecordingFactory. Maybe I should manually change that, but then it feels like I lose the benefits of using the SimpleRecordingFactory over the AdvancedRecordingFactory.

avoitenko-logitech commented 1 year ago

@aza547 Hi. Sorry for delayed answers. I am working on another tasks in parallel. Please try to modify encoder parameters right after its creation. Here is an example code which should help to improve recording quality:

      ...
      recording.videoEncoder = osn.VideoEncoderFactory.create('h264_texture_amf', 'my-video-encoder');
      recording.videoEncoder.update({
          rate_control: 'VBR',
          bitrate: 5000,
          use_bufsize: true,
          buffer_size: 6000,
          crf: 12,
          keyint_sec: 1,
          preset: 'quality',
          profile: 'main',
          tune: 'film',
          repeat_headers: true
      });
      ...

You can also play with values if quality is not good enough. For example, you can try to increase maximum bitrate or decrease the crf (Constant Rate Factor, 0 is lossless quality and 51 is worst possible).

Disclaimer: honestly I do not know how many of these value types actually support the h264_texture_amf encoder, but let it try :-)

aza547 commented 11 months ago

Sorry for the delay - and thanks, I'll give this a go when I get some time.

I was hoping to avoid manually configuring the encoder, but sounds like that isn't possible for the AMD encoders - which is fine, but good to know.

Thanks for the help.