Пример #1
0
        public async Task TranscodeVideo(Stream outputStream, TranscodeVideoFile options, CancellationToken token)
        {
            string cmd;

            if (options.HwAccelDeviceType != HwAccelDeviceType.None)
            {
                cmd = BuildVideoTranscodeCmd(options, 0, 2);

                _logger.LogInformation($"{nameof(TranscodeVideo)}: Checking if we can use the default cmd for hwAccelType = {options.HwAccelDeviceType}...");
                _transcodeProcess.StartInfo.Arguments = cmd;
                _transcodeProcess.Start();
                await using var memStream = new MemoryStream();
                var testStream = _transcodeProcess.StandardOutput.BaseStream as FileStream;
                await testStream.CopyToAsync(memStream, token).ConfigureAwait(false);

                if (_transcodeProcess.ExitCode != 0)
                {
                    _logger.LogWarning(
                        $"{nameof(TranscodeVideo)}: We cant use the default cmd = {cmd} for hwAccelType = {options.HwAccelDeviceType}. " +
                        $"Creating a new one with hwAccelType = {HwAccelDeviceType.None}..");
                    options.HwAccelDeviceType = HwAccelDeviceType.None;
                }
            }

            cmd = BuildVideoTranscodeCmd(options);

            //https://forums.plex.tv/t/best-format-for-streaming-via-chromecast/49978/6
            //ffmpeg - i[inputfile] - c:v libx264 -profile:v high -level 5 - crf 18 - maxrate 10M - bufsize 16M - pix_fmt yuv420p - vf "scale=iw*sar:ih, scale='if(gt(iw,ih),min(1920,iw),-1)':'if(gt(iw,ih),-1,min(1080,ih))'" - x264opts bframes = 3:cabac = 1 - movflags faststart - strict experimental - c:a aac -b:a 320k - y[outputfile]
            //string cmd = $@"-v quiet -ss {seconds} -y -i ""{filePath}"" -preset superfast -c:v copy -acodec aac -b:a 128k -movflags frag_keyframe+faststart -f mp4 -";
            _logger.LogInformation($"{nameof(TranscodeVideo)}: Trying to transcode file with CMD = {cmd}");
            _transcodeProcess.StartInfo.Arguments = cmd;
            _transcodeProcess.Start();
            var stream = _transcodeProcess.StandardOutput.BaseStream as FileStream;
            await stream.CopyToAsync(outputStream, token).ConfigureAwait(false);

            _logger.LogInformation($"{nameof(TranscodeVideo)}: Transcode completed for file = {options.FilePath}");
        }
Пример #2
0
        private static string BuildVideoTranscodeCmd(
            TranscodeVideoFile options,
            double?from = null,
            double?to   = null)
        {
            var builder   = new FFmpegArgsBuilder();
            var inputArgs = builder.AddInputFile(options.FilePath)
                            .BeQuiet()
                            .SetVSync(0)
                            .SetAutoConfirmChanges()
                            .SetHwAccel(options.HwAccelDeviceType)
                            .SetVideoCodec(options.HwAccelDeviceType);
            var outputArgs = builder.AddOutputPipe()
                             .SetPreset(options.HwAccelDeviceType)
                             .AddArg("map_metadata", -1)
                             .AddArg("map_chapters", -1); //for some reason the chromecast doesnt like chapters o.o

            if (options.VideoStreamIndex >= 0)
            {
                outputArgs.SetMap(options.VideoStreamIndex);
            }

            if (options.AudioStreamIndex >= 0)
            {
                outputArgs.SetMap(options.AudioStreamIndex);
            }

            if (options.Seconds > 0 && !from.HasValue && !to.HasValue)
            {
                inputArgs.Seek(options.Seconds);
            }

            if (from.HasValue)
            {
                outputArgs.Seek(from.Value);
            }

            if (to.HasValue)
            {
                outputArgs.To(to.Value);
            }

            if (options.ForceVideoTranscode)
            {
                outputArgs.SetVideoCodec(options.HwAccelDeviceType).SetProfileVideo("main").SetLevel(4).SetPixelFormat(options.HwAccelDeviceType);
                if (options.VideoScaleType != VideoScaleType.Original)
                {
                    int videoScale = (int)options.VideoScaleType;
                    switch (options.HwAccelDeviceType)
                    {
                    case HwAccelDeviceType.Intel:
                        outputArgs.AddArg("global_quality", 25)
                        .AddArg("look_ahead", 1)
                        .SetFilters($"scale_qsv=trunc(oh*a/2)*2:{videoScale}");
                        break;

                    case HwAccelDeviceType.Nvidia:
                        string scale = options.VideoScaleType == VideoScaleType.Hd ? "1280x720" : "1920x1080";
                        if (scale != options.VideoWidthAndHeight && !string.IsNullOrWhiteSpace(options.VideoWidthAndHeight))
                        {
                            inputArgs.AddArg("resize", scale);
                        }
                        break;

                    case HwAccelDeviceType.None:
                        outputArgs.SetFilters($"scale=trunc(oh*a/2)*2:{videoScale}");
                        break;

                    case HwAccelDeviceType.AMD:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
            }
            else
            {
                outputArgs.CopyVideoCodec();
            }

            if (options.ForceAudioTranscode)
            {
                outputArgs.SetAudioCodec("aac").SetAudioBitrate(128).SetAudioChannels(2);
            }
            else
            {
                outputArgs.CopyAudioCodec();
            }

            outputArgs.SetMovFlagToTheStart().SetFormat("mp4");

            return(builder.GetArgs());
        }