From c8e35a9aed068272ddfed8dc23c65d110d5270de Mon Sep 17 00:00:00 2001 From: ww-rm Date: Wed, 20 Aug 2025 22:31:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0mov=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Spine/Exporters/FFmpegVideoExporter.cs | 28 +- SpineViewer/Resources/Strings/en.xaml | 14 +- SpineViewer/Resources/Strings/ja.xaml | 20 +- SpineViewer/Resources/Strings/zh.xaml | 16 +- .../Exporters/FFmpegVideoExporterViewModel.cs | 6 +- .../CustomFFmpegExporterDialog.xaml | 280 ++++++++++-------- .../FFmpegVideoExporterDialog.xaml | 249 +++++++++------- .../ExporterDialogs/FrameExporterDialog.xaml | 172 ++++++----- .../FrameSequenceExporterDialog.xaml | 189 ++++++------ 9 files changed, 562 insertions(+), 412 deletions(-) diff --git a/Spine/Exporters/FFmpegVideoExporter.cs b/Spine/Exporters/FFmpegVideoExporter.cs index adf183b..e3fd2c3 100644 --- a/Spine/Exporters/FFmpegVideoExporter.cs +++ b/Spine/Exporters/FFmpegVideoExporter.cs @@ -31,6 +31,7 @@ namespace Spine.Exporters Mp4, Webm, Mkv, + Mov, } /// @@ -40,29 +41,35 @@ namespace Spine.Exporters private VideoFormat _format = VideoFormat.Mp4; /// - /// 动图是否循环 + /// 动图是否循环 [Gif/Webp] /// public bool Loop { get => _loop; set => _loop = value; } private bool _loop = true; /// - /// 质量 + /// 质量 [Webp] /// public int Quality { get => _quality; set => _quality = Math.Clamp(value, 0, 100); } private int _quality = 75; /// - /// 无损压缩 (Webp) + /// 无损压缩 [Webp] /// public bool Lossless { get => _lossless; set => _lossless = value; } private bool _lossless = false; /// - /// CRF + /// CRF [Mp4/Webm/Mkv] /// public int Crf { get => _crf; set => _crf = Math.Clamp(value, 0, 63); } private int _crf = 23; + /// + /// prores_ks 编码器的配置等级, -1 是自动, 越高质量越好, 只有 4 及以上才有透明通道 [Mov] + /// + public int Profile { get => _profile; set => _profile = Math.Clamp(value, -1, 5); } + private int _profile = 5; + /// /// 获取的一帧, 结果是预乘的 /// @@ -89,6 +96,7 @@ namespace Spine.Exporters VideoFormat.Mp4 => SetMp4Options, VideoFormat.Webm => SetWebmOptions, VideoFormat.Mkv => SetMkvOptions, + VideoFormat.Mov => SetMovOptions, _ => throw new NotImplementedException(), }; @@ -110,8 +118,8 @@ namespace Spine.Exporters { // Gif 固定使用 256 调色板和 128 透明度阈值 var v = "split [s0][s1]"; - var s0 = "[s0] palettegen=reserve_transparent=1:max_colors=256 [p]"; - var s1 = "[s1][p] paletteuse=dither=bayer:alpha_threshold=128"; + var s0 = "[s0] palettegen=max_colors=256 [p]"; + var s1 = "[s1][p] paletteuse=alpha_threshold=128"; var customArgs = $"-vf \"unpremultiply=inplace=1, {v};{s0};{s1}\" -loop {(_loop ? 0 : -1)}"; options.ForceFormat("gif") .WithCustomArgument(customArgs); @@ -151,5 +159,13 @@ namespace Spine.Exporters .WithCustomArgument(customArgs); } + private void SetMovOptions(FFMpegArgumentOptions options) + { + var customArgs = "-vf unpremultiply=inplace=1"; + options.ForceFormat("mov").WithVideoCodec("prores_ks").ForcePixelFormat("yuva444p10le") + .WithFastStart() + .WithCustomArgument($"-profile {_profile}") + .WithCustomArgument(customArgs); + } } } diff --git a/SpineViewer/Resources/Strings/en.xaml b/SpineViewer/Resources/Strings/en.xaml index 2787fdb..f0aae8e 100644 --- a/SpineViewer/Resources/Strings/en.xaml +++ b/SpineViewer/Resources/Strings/en.xaml @@ -149,6 +149,10 @@ Valid max resolution required when using auto resolution FFmpeg export format is required + Base Parameters + Video Parameters + Other Parameters + Screen resolution; adjust related parameters in the render settings panel Export Single When checked, export selected models in a single frame; output folder is required @@ -176,13 +180,15 @@ Video Format Loop Play - Loop animation; only effective for GIF/WebP formats + [Gif/Webp] Whether the animation loops Quality Parameter - Range 0–100; higher is better; only for WebP format + [Webp] Quality parameter, range 0-100, higher value means better quality Lossless Compression - Lossless compression. Ignores the quality parameter and only applies to WebP format. + [Webp] Lossless compression, quality parameter will be ignored CRF Parameter - Range 0–63; lower is higher quality; only for MP4/WebM/MKV formats + [Mp4/Webm/Mkv] CRF parameter, range 0-63, lower value means higher quality + Profile Parameter + [Mov] Profile parameter, integer between -1 and 5, -1 means automatic, higher values indicate higher quality, Alpha channel encoding is only available when value is 4 or higher Export Format FFmpeg export format (equivalent to "-f"), e.g. "mp4", "webm" diff --git a/SpineViewer/Resources/Strings/ja.xaml b/SpineViewer/Resources/Strings/ja.xaml index 803a881..caa0a12 100644 --- a/SpineViewer/Resources/Strings/ja.xaml +++ b/SpineViewer/Resources/Strings/ja.xaml @@ -149,6 +149,10 @@ 自動解像度使用時は有効な最大解像度を指定する必要があります FFmpegエクスポートフォーマットを指定する必要があります + 基本パラメータ + ビデオパラメータ + その他のパラメータ + 画面解像度。関連パラメーターは画面パネルで調整してください 単一エクスポート チェックすると、選択モデルを同一画面でエクスポートし、出力フォルダーの指定が必要になります @@ -176,13 +180,15 @@ ビデオフォーマット ループ再生 - アニメーションをループ再生するか。Gif/Webp形式のみ有効です - 品質パラメーター - 品質パラメーター。値の範囲は0-100。数値が大きいほど品質が高くなります。Webp形式のみ有効です - 可逆圧縮 - 可逆圧縮を行います。品質パラメータは無視され、WebP形式にのみ適用されます。 - CRFパラメーター - CRFパラメーター。値の範囲は0-63。数値が小さいほど品質が高くなります。Mp4/Webm/Mkv形式のみ有効です + [Gif/Webp] アニメーションをループ再生するかどうか + 品質パラメータ + [Webp] 品質パラメータ、範囲は0-100。値が高いほど品質が良い + 無損失圧縮 + [Webp] 無損失圧縮、品質パラメータは無視されます + CRF パラメータ + [Mp4/Webm/Mkv] CRF パラメータ、範囲0-63。値が小さいほど品質が高い + プロファイルパラメータ + [Mov] プロファイルパラメータ、-1から5の整数、 -1は自動、値が大きいほど品質が高い、 値が4以上の場合のみアルファチャンネルをエンコード可能 エクスポートフォーマット FFmpegエクスポートフォーマット。パラメーター“-f”に相当します。例: “mp4”、“webm” diff --git a/SpineViewer/Resources/Strings/zh.xaml b/SpineViewer/Resources/Strings/zh.xaml index 773e757..4131f7d 100644 --- a/SpineViewer/Resources/Strings/zh.xaml +++ b/SpineViewer/Resources/Strings/zh.xaml @@ -149,6 +149,10 @@ 使用自动分辨率时需要提供有效的最大分辨率 必须指定 FFmpeg 导出格式 + 基本参数 + 视频参数 + 其他参数 + 画面分辨率,相关参数请在画面参数面板进行调整 导出单个 勾选后将所选模型在同一个画面上进行导出,且必须提供输出文件夹 @@ -170,19 +174,21 @@ 帧率 导出速度 - 导出速度因子, 仅影响模型的动作速度, 不影响导出时长和帧率等参数 + 导出速度因子,仅影响模型的动作速度,不影响导出时长和帧率等参数 保留最后一帧 当设置保留最后一帧时,动图会更为连贯,但是帧数可能比预期帧数多 1 视频格式 循环播放 - 动图是否循环播放,仅对 Gif/Webp 格式生效 + [Gif/Webp] 动图是否循环播放 质量参数 - 质量参数,取值范围 0-100,越高质量越好, 仅对 Webp 格式生效 + [Webp] 质量参数,取值范围 0-100,越高质量越好 无损压缩 - 无损压缩, 会忽略质量参数, 仅对 Webp 格式生效 + [Webp] 无损压缩,会忽略质量参数 CRF 参数 - CRF 参数,取值范围 0-63,越小质量越高,仅对 Mp4/Webm/Mkv 格式生效 + [Mp4/Webm/Mkv] CRF 参数,取值范围 0-63,越小质量越高 + Profile 参数 + [Mov] Profile 参数,取值集合为 -1 到 5 之间的整数, -1 表示自动,0-5 取值越高质量越高, 仅在取值大于等于 4 时可以编码透明度通道 导出格式 FFmpeg 导出格式,等价于参数 “-f”,例如 “mp4”、“webm” diff --git a/SpineViewer/ViewModels/Exporters/FFmpegVideoExporterViewModel.cs b/SpineViewer/ViewModels/Exporters/FFmpegVideoExporterViewModel.cs index d85d751..df86279 100644 --- a/SpineViewer/ViewModels/Exporters/FFmpegVideoExporterViewModel.cs +++ b/SpineViewer/ViewModels/Exporters/FFmpegVideoExporterViewModel.cs @@ -35,6 +35,9 @@ namespace SpineViewer.ViewModels.Exporters public int Crf { get => _crf; set => SetProperty(ref _crf, Math.Clamp(value, 0, 63)); } protected int _crf = 23; + public int Profile { get => _profile; set => SetProperty(ref _profile, Math.Clamp(value, -1, 5)); } + protected int _profile = 5; + private string FormatSuffix => $".{_format.ToString().ToLower()}"; protected override void Export(SpineObjectModel[] models) @@ -60,7 +63,8 @@ namespace SpineViewer.ViewModels.Exporters Loop = _loop, Quality = _quality, Lossless = _lossless, - Crf = _crf + Crf = _crf, + Profile = _profile, }; // 非自动分辨率则直接用预览画面的视区参数 diff --git a/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml b/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml index 0cf7b22..2ea46ed 100644 --- a/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml +++ b/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml @@ -3,13 +3,14 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:hc="https://handyorg.github.io/handycontrol" xmlns:local="clr-namespace:SpineViewer.Views.ExporterDialogs" xmlns:exporters="clr-namespace:SpineViewer.ViewModels.Exporters" d:DataContext="{d:DesignInstance Type=exporters:CustomFFmpegExporterViewModel}" mc:Ignorable="d" Title="{DynamicResource Str_CustomFFmpegExporterTitle}" Width="450" - Height="650" + Height="800" ShowInTaskbar="False" WindowStartupLocation="CenterOwner"> @@ -27,145 +28,186 @@ + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - + - + + + + + + + + + + + + - - + - + + + + + + + + + + + + + + + + + + + + - - + + + + diff --git a/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml b/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml index a21e325..0260264 100644 --- a/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml +++ b/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml @@ -3,13 +3,14 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:hc="https://handyorg.github.io/handycontrol" xmlns:local="clr-namespace:SpineViewer.Views.ExporterDialogs" xmlns:exporters="clr-namespace:SpineViewer.ViewModels.Exporters" d:DataContext="{d:DesignInstance Type=exporters:FFmpegVideoExporterViewModel}" mc:Ignorable="d" Title="{DynamicResource Str_FFmpegVideoExporterTitle}" Width="450" - Height="580" + Height="750" ShowInTaskbar="False" WindowStartupLocation="CenterOwner"> @@ -27,133 +28,165 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - + + - + diff --git a/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml b/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml index 4469997..7a94059 100644 --- a/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml +++ b/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml @@ -10,7 +10,7 @@ mc:Ignorable="d" Title="{DynamicResource Str_FrameExporterTitle}" Width="450" - Height="400" + Height="480" ShowInTaskbar="False" WindowStartupLocation="CenterOwner"> @@ -28,94 +28,112 @@ - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + + + - - + + + + diff --git a/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml b/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml index 9310b6b..9362b8c 100644 --- a/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml +++ b/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml @@ -3,13 +3,14 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:hc="https://handyorg.github.io/handycontrol" xmlns:local="clr-namespace:SpineViewer.Views" xmlns:vmexp="clr-namespace:SpineViewer.ViewModels.Exporters" d:DataContext="{d:DesignInstance Type=vmexp:FrameSequenceExporterViewModel}" mc:Ignorable="d" Title="{DynamicResource Str_FrameSequenceExporterTitle}" Width="450" - Height="450" + Height="550" ShowInTaskbar="False" WindowStartupLocation="CenterOwner"> @@ -27,104 +28,122 @@ - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - + - + + + + + + + + + + + + - - + + + +