Inheritance: MarkupExtension, ICommand
        static void Main(string[] args)
        {
            var configurations = AppSettings.RabbitMqConfigurations;
            var bus            = BusCreator.Create(configurations);
            var sendToUri      = new Uri($"{configurations.Uri}{configurations.WindowsServiceQueue}");

            var text = string.Empty;

            while (text != "quit")
            {
                Console.Write("Enter a message: ");
                text = Console.ReadLine();

                var message = new WindowsServiceCommand
                {
                    Id       = Guid.NewGuid(),
                    Message  = text,
                    DateTime = DateTime.Now
                };

                Task.Run(() => CommandExtension.SendCommand(bus, sendToUri, message));
            }
        }
Ejemplo n.º 2
0
        public List <TaskCommand> Generate(Dictionary <string, JToken> sectionData)
        {
            #region 输入/输出

            JToken ioSection =
                sectionData[ConfigSectionBase.IOConfigSectionId];

            #endregion

            #region 输入文件

            string inputPathIntl = PathExtension.GetFullPathOrEmpty(ioSection["input"]?.ToObject <string>() ?? string.Empty);
            string inputPath     = inputPathIntl.EscapePathStringForArg();

            #endregion

            #region 输入字幕

            string subtitlePathIntl = PathExtension.GetFullPathOrEmpty(ioSection["subtitle"]?.ToObject <string>() ?? string.Empty);
            string subtitlePath     = subtitlePathIntl.EscapePathStringForArg();

            #endregion

            #region 字幕相关

            bool isIncludingSubtitle = !string.IsNullOrWhiteSpace(subtitlePathIntl);

            #endregion

            #region VapourSynth 相关

            string lwiPath = (inputPathIntl + ".lwi").EscapePathStringForArg();

            bool isVpy = inputPathIntl.EndsWith(".vpy");

            bool useVpy = isVpy || isIncludingSubtitle;

            if (isVpy && isIncludingSubtitle)
            {
                throw new OperationException(
                          "不支持在 VapourSynth 输入上使用 VSFilterMod。请在 VapourSynth 中完成字幕处理。",
                          typeof(HwEncOperation));
            }

            #endregion

            #region 显卡相关

            JToken hwEncQualitySection =
                sectionData["Ruminoid.Toolbox.Plugins.HwEnc.ConfigSections.HwEncQualityConfigSection"];
            JToken hwEncCodecSection =
                sectionData["Ruminoid.Toolbox.Plugins.HwEnc.ConfigSections.HwEncCodecConfigSection"];
            JToken hwEncCoreSection =
                sectionData["Ruminoid.Toolbox.Plugins.HwEnc.ConfigSections.HwEncCoreConfigSection"];

            string hwEncCore = hwEncCoreSection["core"]?.ToObject <string>();

            string vtempPath = Path.ChangeExtension(inputPathIntl, "vtemp.mp4").EscapePathStringForArg();

            #endregion

            #region 音频

            JToken audioSection =
                sectionData["Ruminoid.Toolbox.Plugins.Audio.ConfigSections.AudioConfigSection"];

            #endregion

            #region 音频相关

            string atempPath = Path.ChangeExtension(inputPathIntl, "atemp.mp4").EscapePathStringForArg();

            string audioMode = audioSection["mode"]?.ToObject <string>();

            bool hasAudio       = audioMode != "none";
            bool isVpyWithAudio = useVpy && hasAudio;

            int audioBitrate = audioSection["bitrate"].ToObject <int>();

            string audioArgs = audioMode switch
            {
                "process" => "--audio-codec --audio-bitrate " + audioBitrate,
                "none" => "",
                _ => "--audio-copy"
            };

            #endregion

            #region 输出相关

            string outputPath = PathExtension.GetFullPathOrEmpty(ioSection["output"]?.ToObject <string>() ?? string.Empty).EscapePathStringForArg();

            #endregion

            #region 自定义参数

            JToken customArgsSection =
                sectionData["Ruminoid.Toolbox.Plugins.Common.ConfigSections.CustomArgsConfigSection"];

            string customArgs    = customArgsSection["args"]?.ToObject <string>();
            bool   useCustomArgs = customArgsSection["use_custom_args"]?.ToObject <bool>() ?? false;

            #endregion

            #region 准备命令

            List <TaskCommand> result = new();

            #endregion

            // 开始处理

            #region 处理音频

            if (isVpyWithAudio)
            {
                result.Add(new(
                               "ffmpeg",
                               $"-i {inputPath} -vn -sn -c:a copy -y -map 0:a:0 {atempPath}",
                               "null"));
            }

            #endregion

            #region 处理字幕

            if (isIncludingSubtitle)
            {
                string vpyPath = Path.ChangeExtension(inputPathIntl, "vpy").EscapePathStringForArg();

                result.Add(
                    ("node",
                     $"rmbox-vpygen.js {inputPath} {subtitlePath} {vpyPath}",
                     "null"));

                inputPath = vpyPath;
            }

            #endregion

            #region 处理视频

            string encodeMode = hwEncQualitySection["encode_mode"]?.ToObject <string>() switch
            {
                "cqp" => $"--cqp {hwEncQualitySection["cqp_value"]?.ToObject<string>()}",
                "2pass" => $"--vbr {hwEncQualitySection["2pass_value"]?.ToObject<int>()} --multipass 2pass-full",
                // ReSharper disable once NotResolvedInText
                _ => throw new ArgumentOutOfRangeException("encode_mode")
            };

            result.Add(
                (hwEncCore,
                 $"{(useVpy ? "--vpy" : "--avhw")} -i {inputPath} -o {outputPath} {(isVpyWithAudio ? "--audio-source " + atempPath : "")} {audioArgs} --codec {hwEncCodecSection["codec"]?.ToObject<string>()} {encodeMode} {(useCustomArgs ? customArgs : DefaultArgs)}",
                 hwEncCore));

            #endregion

            #region 清理临时文件

            result.AddRange(new[]
            {
                vtempPath, atempPath, lwiPath
            }
                            .Select(CommandExtension.GenerateTryDeleteCommand)
                            .ToList());

            if (isIncludingSubtitle)
            {
                result.Add(CommandExtension.GenerateTryDeleteCommand(inputPath));
            }

            #endregion

            return(result);
        }
Ejemplo n.º 3
0
        public List <TaskCommand> Generate(Dictionary <string, JToken> sectionData)
        {
            #region 输入/输出

            JToken ioSection =
                sectionData[ConfigSectionBase.IOConfigSectionId];

            #endregion

            #region 输入文件

            string inputPathIntl = PathExtension.GetFullPathOrEmpty(ioSection["input"]?.ToObject <string>() ?? string.Empty);
            string inputPath     = inputPathIntl.EscapePathStringForArg();

            #endregion

            #region 输入字幕

            string subtitlePathIntl = PathExtension.GetFullPathOrEmpty(ioSection["subtitle"]?.ToObject <string>() ?? string.Empty);
            string subtitlePath     = subtitlePathIntl.EscapePathStringForArg();

            #endregion

            #region 字幕相关

            bool isIncludingSubtitle = !string.IsNullOrWhiteSpace(subtitlePathIntl);

            #endregion

            #region VapourSynth 相关

            string lwiPath = (inputPathIntl + ".lwi").EscapePathStringForArg();

            bool isVpy = inputPathIntl.EndsWith(".vpy");

            bool useVpy = isVpy || isIncludingSubtitle;

            if (isVpy && isIncludingSubtitle)
            {
                throw new OperationException(
                          "不支持在 VapourSynth 输入上使用 VSFilterMod。请在 VapourSynth 中完成字幕处理。",
                          typeof(X264EncodeOperation));
            }

            #endregion

            #region x264 分离器

            JToken x264DemuxerSection =
                sectionData["Ruminoid.Toolbox.Plugins.X264.ConfigSections.X264DemuxerConfigSection"];

            string demuxer = x264DemuxerSection["demuxer"]?.ToObject <string>();

            string demuxerArgs = string.IsNullOrWhiteSpace(demuxer) || demuxer == "auto" ? "" : "--demuxer " + demuxer;

            #endregion

            #region x264 质量

            JToken x264QualitySection =
                sectionData["Ruminoid.Toolbox.Plugins.X264.ConfigSections.X264EncodeQualityConfigSection"];

            #endregion

            #region x264 核心

            JToken x264CoreSection =
                sectionData["Ruminoid.Toolbox.Plugins.X264.ConfigSections.X264CoreConfigSection"];

            #endregion

            #region x264 相关

            string vtempPath            = Path.ChangeExtension(inputPathIntl, "vtemp.mp4").EscapePathStringForArg();
            string vtempStatsPath       = Path.ChangeExtension(inputPathIntl, "vtemp.stats").EscapePathStringForArg();
            string vtempStatsMbtreePath = Path.ChangeExtension(inputPathIntl, "vtemp.stats.mbtree").EscapePathStringForArg();

            string x264EncodeMode = x264QualitySection["encode_mode"]?.ToObject <string>() ?? string.Empty;

            string x264Core = x264CoreSection["core"]?.ToObject <string>();

            #endregion

            #region 音频

            JToken audioSection =
                sectionData["Ruminoid.Toolbox.Plugins.Audio.ConfigSections.AudioConfigSection"];

            #endregion

            #region 音频相关

            string atempPath = Path.ChangeExtension(inputPathIntl, "atemp.mp4").EscapePathStringForArg();

            string audioMode    = audioSection["mode"]?.ToObject <string>();
            bool   hasAudio     = audioMode != "none";
            int    audioBitrate = audioSection["bitrate"].ToObject <int>();

            #endregion

            #region 输出相关

            string outputPath = PathExtension.GetFullPathOrEmpty(ioSection["output"]?.ToObject <string>() ?? string.Empty).EscapePathStringForArg();

            #endregion

            #region 自定义参数

            JToken customArgsSection =
                sectionData["Ruminoid.Toolbox.Plugins.Common.ConfigSections.CustomArgsConfigSection"];

            string customArgs    = customArgsSection["args"]?.ToObject <string>();
            bool   useCustomArgs = customArgsSection["use_custom_args"]?.ToObject <bool>() ?? false;

            #endregion

            #region 准备命令

            List <TaskCommand> result = new();

            #endregion

            // 开始处理

            #region 处理音频

            switch (audioMode)
            {
            case "copy":
                result.Add(new(
                               "ffmpeg",
                               $"-i {inputPath} -vn -sn -c:a copy -y -map 0:a:0 {atempPath}",
                               "null"));
                break;

            case "process":
                result.Add(new(
                               "ffmpeg",
                               $"-i {inputPath} -vn -sn -v 0 -c:a pcm_s16le -f wav pipe: | {PathExtension.GetTargetPath("qaac64")} -q 2 --ignorelength -c {audioBitrate} - -o {atempPath}",
                               "null"));
                break;
            }

            #endregion

            #region 处理字幕

            if (isIncludingSubtitle)
            {
                string vpyPath = Path.ChangeExtension(inputPathIntl, "vpy").EscapePathStringForArg();

                result.Add(
                    ("node",
                     $"rmbox-vpygen.js {inputPath} {subtitlePath} {vpyPath}",
                     "null"));

                inputPath = vpyPath;
            }

            #endregion

            #region 处理 x264 参数

            string x264Args = $"{(useCustomArgs ? customArgs : DefaultArgs)} {(isIncludingSubtitle && !isIncludingSubtitle ? "--vf subtitles --sub " + subtitlePath : "")}";

            #endregion

            #region 处理视频

            switch (x264EncodeMode)
            {
            case "crf":
                result.Add(
                    GenerateVideoProcessingCommand(
                        $"--crf {x264QualitySection["crf_value"]?.ToObject<double>():N1} {demuxerArgs} {x264Args} -o {(hasAudio ? vtempPath : outputPath)}",
                        x264Core,
                        inputPath,
                        useVpy));
                break;

            case "2pass":
                result.AddRange(new[]
                {
                    GenerateVideoProcessingCommand(
                        $"--pass 1 --bitrate {x264QualitySection["2pass_value"]?.ToObject<int>()} {demuxerArgs} --stats {vtempStatsPath} {x264Args} -o NUL",
                        x264Core,
                        inputPath,
                        useVpy),
                    GenerateVideoProcessingCommand(
                        $"--pass 2 --bitrate {x264QualitySection["2pass_value"]?.ToObject<int>()} {demuxerArgs} --stats {vtempStatsPath} {x264Args} -o {(hasAudio ? vtempPath : outputPath)}",
                        x264Core,
                        inputPath,
                        useVpy)
                });
                break;

            default:
                // ReSharper disable once NotResolvedInText
                throw new ArgumentOutOfRangeException("encode_mode");
            }

            #endregion

            #region 混流

            if (hasAudio)
            {
                result.Add(new(
                               "ffmpeg",
                               $"-i {vtempPath} -i {atempPath} -vcodec copy -acodec copy -y {outputPath}",
                               "ffmpeg"));
            }

            #endregion

            #region 清理临时文件

            result.AddRange(new[]
            {
                vtempPath, atempPath, vtempStatsPath, vtempStatsMbtreePath, lwiPath
            }
                            .Select(CommandExtension.GenerateTryDeleteCommand)
                            .ToList());

            if (isIncludingSubtitle)
            {
                result.Add(CommandExtension.GenerateTryDeleteCommand(inputPath));
            }

            #endregion

            return(result);
        }