diff --git a/Bundle/Linux/scenes b/Bundle/Linux/scenes index cfa78d4..de70c6f 100644 Binary files a/Bundle/Linux/scenes and b/Bundle/Linux/scenes differ diff --git a/Bundle/OSX/scenes b/Bundle/OSX/scenes index 87939f1..d6419d8 100644 Binary files a/Bundle/OSX/scenes and b/Bundle/OSX/scenes differ diff --git a/Bundle/Win64/scenes b/Bundle/Win64/scenes index 81d4425..343a892 100644 Binary files a/Bundle/Win64/scenes and b/Bundle/Win64/scenes differ diff --git a/Core/RenderManager.cs b/Core/RenderManager.cs index 7ee914a..b277c59 100644 --- a/Core/RenderManager.cs +++ b/Core/RenderManager.cs @@ -387,7 +387,7 @@ namespace ADOFAIRenderer.Core private IEnumerator SetupPlay() { - if (Configuration.RenderAudio && GetOutputExtension(Configuration.EncodingConfig!.Codec) != ".mp4") + if (Configuration.RenderAudio && GetOutputExtension(Configuration.VideoConfig!.Codec) != ".mp4") { Configuration.AudioSampleRate = 48000; } @@ -475,7 +475,7 @@ namespace ADOFAIRenderer.Core var renderFPS = Configuration.RenderFPS; var videoFPS = Configuration.VideoFPS; - var selectedCodec = Configuration.EncodingConfig?.Codec ?? Codec.H264; + var selectedCodec = Configuration.VideoConfig?.Codec ?? Codec.H264; var ext = GetOutputExtension(selectedCodec); var startTime = DateTime.Now; @@ -493,12 +493,12 @@ namespace ADOFAIRenderer.Core Height = Configuration.RenderHeight, FPS = effectiveVideoFps, Codec = selectedCodec, - Mode = Configuration.EncodingConfig!.RateControlMode, - QualityValue = Configuration.EncodingConfig.QP, - TargetBitrate = Configuration.EncodingConfig.Bitrate, - MaxBitrate = Configuration.EncodingConfig.MaxBitrate, - GopSize = Configuration.EncodingConfig.KeyframeInterval, - ForceSoftware = Configuration.EncodingConfig.ForceSoftwareEncoder, + Mode = Configuration.VideoConfig!.RateControlMode, + QualityValue = Configuration.VideoConfig.QP, + TargetBitrate = Configuration.VideoConfig.Bitrate, + MaxBitrate = Configuration.VideoConfig.MaxBitrate, + GopSize = Configuration.VideoConfig.KeyframeInterval, + ForceSoftware = Configuration.VideoConfig.ForceSoftwareEncoder, Audio = Configuration.RenderAudio ? new FFmpegNativeEncoder.AudioSettings { SampleRate = Configuration.AudioSampleRate, diff --git a/Data/PresetManager.cs b/Data/PresetManager.cs index e406e48..2013c72 100644 --- a/Data/PresetManager.cs +++ b/Data/PresetManager.cs @@ -75,20 +75,46 @@ namespace ADOFAIRenderer.Data var configToken = jObject["Config"]; if (configToken is JObject configObj) { + // 1. legacy EncodingConfig -> VideoConfig + if (configObj["EncodingConfig"] is JObject oldEncodingConfigObj) + { + configObj["VideoConfig"] ??= oldEncodingConfigObj; + configObj.Remove("EncodingConfig"); + } + + // 2. legacy top-level Codec -> VideoConfig.Codec var legacyCodecToken = configObj["Codec"]; if (legacyCodecToken != null) { - var encodingConfigToken = configObj["EncodingConfig"]; - if (encodingConfigToken == null) + if (configObj["VideoConfig"] == null) { - configObj["EncodingConfig"] = new JObject(); + configObj["VideoConfig"] = new JObject(); } - var encodingConfigObj = (JObject)configObj["EncodingConfig"]!; - encodingConfigObj["Codec"] ??= legacyCodecToken; + var videoConfigObj = (JObject)configObj["VideoConfig"]!; + videoConfigObj["Codec"] ??= legacyCodecToken; configObj.Remove("Codec"); } + + // 3. legacy top-level Audio properties -> AudioConfig + if (configObj["AudioConfig"] == null) + { + var audioConfigObj = new JObject(); + if (configObj["RenderAudio"] != null) + audioConfigObj["RenderAudio"] = configObj["RenderAudio"]; + if (configObj["AudioSampleRate"] != null) + audioConfigObj["AudioSampleRate"] = configObj["AudioSampleRate"]; + if (configObj["AudioChannels"] != null) + audioConfigObj["AudioChannels"] = configObj["AudioChannels"]; + if (configObj["AudioBitrate"] != null) + audioConfigObj["AudioBitrate"] = configObj["AudioBitrate"]; + + if (audioConfigObj.HasValues) + { + configObj["AudioConfig"] = audioConfigObj; + } + } } var preset = jObject.ToObject(); diff --git a/Data/RenderConfig.cs b/Data/RenderConfig.cs index 3007edd..6a4cba0 100644 --- a/Data/RenderConfig.cs +++ b/Data/RenderConfig.cs @@ -10,20 +10,42 @@ namespace ADOFAIRenderer.Data public int RenderWidth { get; set; } public int RenderHeight { get; set; } - public EncodingConfig? EncodingConfig { get; set; } + public VideoEncodingConfig? VideoConfig { get; set; } + public AudioEncodingConfig? AudioConfig { get; set; } public double DelayAfterLevelEnd { get; set; } public bool ShowJudgementText { get; set; } public int? RandomSeed { get; set; } = null; public bool ProcessAudio { get; set; } - public bool RenderAudio { get; set; } = true; - public int AudioSampleRate { get; set; } = 44100; - public int AudioChannels { get; set; } = 2; - public int AudioBitrate { get; set; } = 256000; + + // 하위 호환 및 편의를 위한 접근자 + public bool RenderAudio + { + get => AudioConfig?.RenderAudio ?? true; + set => (AudioConfig ??= new AudioEncodingConfig()).RenderAudio = value; + } + + public int AudioSampleRate + { + get => AudioConfig?.AudioSampleRate ?? 44100; + set { (AudioConfig ??= new AudioEncodingConfig()).AudioSampleRate = value; } + } + + public int AudioChannels + { + get => AudioConfig?.AudioChannels ?? 2; + set { (AudioConfig ??= new AudioEncodingConfig()).AudioChannels = value; } + } + + public int AudioBitrate + { + get => AudioConfig?.AudioBitrate ?? 256000; + set { (AudioConfig ??= new AudioEncodingConfig()).AudioBitrate = value; } + } } - public class EncodingConfig + public class VideoEncodingConfig { public Codec Codec { get; set; } = Codec.H264; public RateControlMode RateControlMode { get; set; } @@ -35,4 +57,12 @@ namespace ADOFAIRenderer.Data public double KeyframeInterval { get; set; } public bool ForceSoftwareEncoder { get; set; } } + + public class AudioEncodingConfig + { + public bool RenderAudio { get; set; } = true; + public int AudioSampleRate { get; set; } = 44100; + public int AudioChannels { get; set; } = 2; + public int AudioBitrate { get; set; } = 256000; + } } \ No newline at end of file diff --git a/UI/RenderConfigUIManager.cs b/UI/RenderConfigUIManager.cs index 2e09fd0..ca7cc2f 100644 --- a/UI/RenderConfigUIManager.cs +++ b/UI/RenderConfigUIManager.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using ADOFAIRenderer.Core; using ADOFAIRenderer.Data; using ADOFAIRenderer.Util.FFmpeg; @@ -17,8 +18,11 @@ namespace ADOFAIRenderer.UI private DoubleInputValidator _doubleValidator = null!; private Button _goRenderButton = null!; - private Button _encodingConfigButton = null!; - private VisualElement _encodingConfigContainer = null!; + private Button _videoEncodingConfigButton = null!; + private VisualElement _videoEncodingConfigContainer = null!; + + private Button _audioEncodingConfigButton = null!; + private VisualElement _audioEncodingConfigContainer = null!; private void Awake() { @@ -48,15 +52,26 @@ namespace ADOFAIRenderer.UI _goRenderButton = _root.Q