Пример #1
0
        public static string GetSubtitleExtension(SubtitleCodec codec)
        {
            switch (codec)
            {
            case SubtitleCodec.Srt:
                return("srt");

            case SubtitleCodec.MicroDvd:
                return("sub");

            case SubtitleCodec.SubView:
                return("sub");

            case SubtitleCodec.Ass:
                return("ass");

            case SubtitleCodec.Ssa:
                return("ssa");

            case SubtitleCodec.Smi:
                return("smi");

            case SubtitleCodec.WebVtt:
                return("vtt");
            }
            return("mpts");
        }
Пример #2
0
        public static string GetSubtitleMime(SubtitleCodec codec)
        {
            switch (codec)
            {
            case SubtitleCodec.Srt:
                return("text/srt");

            case SubtitleCodec.MicroDvd:
                return("text/microdvd");

            case SubtitleCodec.SubView:
                return("text/plain");

            case SubtitleCodec.Ass:
                return("text/x-ass");

            case SubtitleCodec.Ssa:
                return("text/x-ssa");

            case SubtitleCodec.Smi:
                return("smi/caption");

            case SubtitleCodec.WebVtt:
                return("text/vtt");
            }
            return("text/plain");
        }
Пример #3
0
        public async Task AddSubtitleWithLanguageAndCodecTest(SubtitleCodec subtitleCodec)
        {
            string output = Path.ChangeExtension(Path.GetTempFileName(), FileExtensions.Mkv);
            string input  = Resources.MkvWithAudio;

            var language             = "pol";
            IConversionResult result = await(await FFmpeg.Conversions.FromSnippet.AddSubtitle(input, output, Resources.SubtitleSrt, subtitleCodec, language))
                                       .SetPreset(ConversionPreset.UltraFast)
                                       .Start();


            IMediaInfo outputInfo = await FFmpeg.GetMediaInfo(output);

            Assert.Equal(TimeSpan.FromSeconds(3071), outputInfo.Duration);
            Assert.Single(outputInfo.SubtitleStreams);
            Assert.Single(outputInfo.VideoStreams);
            Assert.Single(outputInfo.AudioStreams);
            Assert.Equal(language, outputInfo.SubtitleStreams.First().Language);

            if (subtitleCodec.ToString() == "copy")
            {
                Assert.Equal("subrip", outputInfo.SubtitleStreams.First().Codec);
            }
            else if (subtitleCodec.ToString() == "ssa")
            {
                Assert.Equal("ass", outputInfo.SubtitleStreams.First().Codec);
            }
            else
            {
                Assert.Equal(subtitleCodec.ToString(), outputInfo.SubtitleStreams.First().Codec);
            }
        }
        public static string GetSubtitleContainer(SubtitleCodec codec)
        {
            switch (codec)
            {
            case SubtitleCodec.Srt:
                return("srt");

            case SubtitleCodec.MicroDvd:
                return("microdvd");

            case SubtitleCodec.SubView:
                return("subviewer");

            case SubtitleCodec.Ass:
                return("ass");

            case SubtitleCodec.Ssa:
                return("ssa");

            case SubtitleCodec.Smi:
                return("sami");

            case SubtitleCodec.MovTxt:
                return("mov_text");

            case SubtitleCodec.DvbSub:
                return("dvbsub");

            case SubtitleCodec.WebVtt:
                return("webvtt");
            }
            return("copy");
        }
Пример #5
0
        public async Task AddSubtitleWithCodecTest(SubtitleCodec subtitleCodec)
        {
            string output = Path.ChangeExtension(Path.GetTempFileName(), FileExtensions.Mkv);
            string input  = Resources.MkvWithAudio;

            IConversionResult result = await(await FFmpeg.Conversions.FromSnippet.AddSubtitle(input, output, Resources.SubtitleSrt, subtitleCodec))
                                       .Start();

            IMediaInfo outputInfo = await FFmpeg.GetMediaInfo(output);

            Assert.Equal(51, outputInfo.Duration.Minutes);
            Assert.Single(outputInfo.SubtitleStreams);
            Assert.Single(outputInfo.VideoStreams);
            Assert.Single(outputInfo.AudioStreams);

            if (subtitleCodec.ToString() == "copy")
            {
                Assert.Equal("subrip", outputInfo.SubtitleStreams.First().Codec);
            }
            else if (subtitleCodec.ToString() == "ssa")
            {
                Assert.Equal("ass", outputInfo.SubtitleStreams.First().Codec);
            }
            else
            {
                Assert.Equal(subtitleCodec.ToString(), outputInfo.SubtitleStreams.First().Codec);
            }
        }
Пример #6
0
        public static bool IsImageBasedSubtitle(SubtitleCodec codec)
        {
            if (codec == SubtitleCodec.DvbSub || codec == SubtitleCodec.VobSub)
            {
                return(true);
            }

            return(false);
        }
Пример #7
0
 public static bool IsSubtitleSupportedByContainer(SubtitleCodec codec, VideoContainer sourceContainer, VideoContainer targetContainer)
 {
     if (targetContainer != VideoContainer.Unknown && sourceContainer == targetContainer)
     {
         return(true);
     }
     if (targetContainer == VideoContainer.Matroska && (codec == SubtitleCodec.VobSub || codec == SubtitleCodec.Ass ||
                                                        codec == SubtitleCodec.MicroDvd || codec == SubtitleCodec.Smi || codec == SubtitleCodec.Srt || codec == SubtitleCodec.Ssa ||
                                                        codec == SubtitleCodec.SubView))
     {
         return(true);
     }
     if (targetContainer == VideoContainer.Mpeg2Ps && codec == SubtitleCodec.VobSub)
     {
         return(true);
     }
     if (targetContainer == VideoContainer.Mpeg2Ts && (codec == SubtitleCodec.DvbSub || codec == SubtitleCodec.DvbTxt))
     {
         return(true);
     }
     if (targetContainer == VideoContainer.Avi && codec == SubtitleCodec.Srt)
     {
         return(true);
     }
     if (targetContainer == VideoContainer.Asf && codec == SubtitleCodec.Srt)
     {
         return(true);
     }
     if (targetContainer == VideoContainer.Hls && codec == SubtitleCodec.MovTxt)
     {
         return(true);
     }
     if (targetContainer == VideoContainer.M2Ts && codec == SubtitleCodec.VobSub)
     {
         return(true);
     }
     if (targetContainer == VideoContainer.Mp4 && codec == SubtitleCodec.MovTxt)
     {
         return(true);
     }
     if (targetContainer == VideoContainer.Hls && codec == SubtitleCodec.WebVtt)
     {
         return(true);
     }
     if (targetContainer == VideoContainer.Mpeg1 && codec == SubtitleCodec.VobSub)
     {
         return(true);
     }
     return(false);
 }
        public static string GetSubtitleBaseURL(Guid mediaItemId, EndPointSettings client, out string subMime, out string subExtension)
        {
            SubtitleCodec codec = SubtitleCodec.Unknown;

            subMime      = null;
            subExtension = null;

            if (UseSoftCodedSubtitle(client, out codec, out subMime) == true)
            {
                subExtension = SubtitleHelper.GetSubtitleExtension(codec);
                string subType = codec.ToString();
                return(string.Format(GetBaseResourceURL()
                                     + GetResourceUrl(mediaItemId.ToString(), client.ClientId)
                                     + "&aspect=SUBTITLE&type={0}&file=subtitle.{1}", subType, subExtension));
            }
            return(null);
        }
Пример #9
0
        /// <summary>
        /// Returns the appropriate extension given an subtitle codec
        /// </summary>
        /// <param name="subtitleCodec"></param>
        /// <returns></returns>
        public static Extension GetSubtitleExtension(SubtitleCodec subtitleCodec)
        {
            if (subtitleCodec.Codec == SubtitleCodec.PGS.Codec)
            {
                return(Extension.SUP);
            }

            if (subtitleCodec.Codec == SubtitleCodec.KATE.Codec)
            {
                return(Extension.OGG);
            }

            if (subtitleCodec.Codec == SubtitleCodec.TEXT_SSA.Codec || subtitleCodec.Codec == SubtitleCodec.SSA.Codec)
            {
                return(Extension.SSA);
            }

            if (subtitleCodec.Codec == SubtitleCodec.TEXT_ASS.Codec || subtitleCodec.Codec == SubtitleCodec.ASS.Codec)
            {
                return(Extension.ASS);
            }

            if (subtitleCodec.Codec == SubtitleCodec.TEXT_ASCII.Codec || subtitleCodec.Codec == SubtitleCodec.TEXT_UTF.Codec)
            {
                return(Extension.SRT);
            }

            if (subtitleCodec.Codec == SubtitleCodec.TEXT_USF.Codec)
            {
                return(Extension.USF);
            }

            if (subtitleCodec.Codec == SubtitleCodec.TEXT_WEB.Codec)
            {
                return(Extension.WEBVTT);
            }

            if (subtitleCodec.Codec == SubtitleCodec.SUB.Codec)
            {
                return(Extension.SUB);
            }

            throw new UnkownExtentionException($"Unkown extension for codec: {subtitleCodec.Codec}");
        }
 public static bool UseSoftCodedSubtitle(EndPointSettings client, out SubtitleCodec targetCodec, out string targetMime)
 {
     targetCodec = SubtitleCodec.Unknown;
     targetMime  = "text/plain";
     if (client.Profile.MediaTranscoding.SubtitleSettings.SubtitleMode == SubtitleSupport.SoftCoded)
     {
         targetCodec = client.Profile.MediaTranscoding.SubtitleSettings.SubtitlesSupported[0].Format;
         if (string.IsNullOrEmpty(client.Profile.MediaTranscoding.SubtitleSettings.SubtitlesSupported[0].Mime) == false)
         {
             targetMime = client.Profile.MediaTranscoding.SubtitleSettings.SubtitlesSupported[0].Mime;
         }
         else
         {
             targetMime = SubtitleHelper.GetSubtitleMime(targetCodec);
         }
         return(true);
     }
     return(false);
 }
Пример #11
0
        public async Task BasicTranscode_InputFileWithSubtitles_SkipSubtitlesWithParameter(VideoCodec videoCodec, AudioCodec audioCodec, SubtitleCodec subtitleCodec)
        {
            string output = _storageFixture.GetTempFileName(FileExtensions.Mp4);

            IConversionResult result = await(await FFmpeg.Conversions.FromSnippet.Transcode(Resources.MkvWithSubtitles, output, videoCodec, audioCodec, subtitleCodec, false)).Start();


            IMediaInfo mediaInfo = await FFmpeg.GetMediaInfo(output);

            Assert.Equal(9, mediaInfo.Duration.Seconds);
            Assert.Single(mediaInfo.VideoStreams);
            Assert.Single(mediaInfo.AudioStreams);
            Assert.Empty(mediaInfo.SubtitleStreams);
            IAudioStream audioStream = mediaInfo.AudioStreams.First();
            IVideoStream videoStream = mediaInfo.VideoStreams.First();

            Assert.NotNull(videoStream);
            Assert.NotNull(audioStream);
            Assert.Equal(videoCodec.ToString(), videoStream.Codec);
            Assert.Equal(audioCodec.ToString(), audioStream.Codec);
            Assert.Equal(25, videoStream.Framerate);
        }
Пример #12
0
        /// <inheritdoc />
        public ISubtitleStream SetCodec(SubtitleCodec codec)
        {
            string input = codec.ToString();

            return(SetCodec($"{input}"));
        }
        protected override async Task <TranscodeContext> TranscodeVideoAsync(string clientId, VideoTranscoding video, double timeStart, double timeDuration, bool waitForBuffer)
        {
            FFMpegTranscodeContext context = new FFMpegTranscodeContext(_cacheEnabled, _cachePath);

            context.TargetDuration = video.SourceMediaDuration;
            if (timeStart == 0 && video.TargetIsLive == false && _cacheEnabled)
            {
                timeDuration    = 0;
                context.Partial = false;
            }
            else if (video.TargetVideoContainer == VideoContainer.Hls)
            {
                context.Partial = true;
            }
            else
            {
                video.TargetIsLive = true;
                context.Partial    = true;
            }
            if (video.TargetVideoContainer == VideoContainer.Unknown)
            {
                video.TargetVideoContainer = video.SourceVideoContainer;
            }

            bool          embeddedSupported = false;
            SubtitleCodec embeddedSubCodec  = SubtitleCodec.Unknown;

            if (video.TargetSubtitleSupport == SubtitleSupport.Embedded)
            {
                if (video.TargetVideoContainer == VideoContainer.Matroska)
                {
                    embeddedSupported         = true;
                    embeddedSubCodec          = SubtitleCodec.Ass;
                    video.TargetSubtitleCodec = SubtitleCodec.Ass;
                }
                else if (video.TargetVideoContainer == VideoContainer.Mp4)
                {
                    embeddedSupported         = true;
                    embeddedSubCodec          = SubtitleCodec.MovTxt;
                    video.TargetSubtitleCodec = SubtitleCodec.MovTxt;
                }
                else if (video.TargetVideoContainer == VideoContainer.Hls)
                {
                    embeddedSupported         = true;
                    embeddedSubCodec          = SubtitleCodec.WebVtt;
                    video.TargetSubtitleCodec = SubtitleCodec.WebVtt;
                }
                else if (video.TargetVideoContainer == VideoContainer.Avi)
                {
                    embeddedSupported         = true;
                    embeddedSubCodec          = SubtitleCodec.Srt;
                    video.TargetSubtitleCodec = SubtitleCodec.Srt;
                }
                //else if (video.TargetVideoContainer == VideoContainer.Mpeg2Ts)
                //{
                //  embeddedSupported = true;
                //  embeddedSubCodec = SubtitleCodec.DvbSub;
                //  video.TargetSubtitleCodec = SubtitleCodec.VobSub;
                //}
                else
                {
                    _logger.Debug("FFMpegMediaConverter: Container {0} does not support embedded subtitles", video.TargetVideoContainer);
                }
            }
            video.TargetSubtitleMime       = SubtitleHelper.GetSubtitleMime(video.TargetSubtitleCodec);
            video.PreferredSourceSubtitles = await GetSubtitlesAsync(clientId, video, timeStart).ConfigureAwait(false);

            string transcodingFile = GetTranscodingVideoFileName(video, timeStart, embeddedSupported);

            transcodingFile = Path.Combine(_cachePath, transcodingFile);

            if (File.Exists(transcodingFile))
            {
                //Use non-partial transcode if possible
                TranscodeContext existingContext = await GetExistingTranscodeContextAsync(clientId, video.TranscodeId).ConfigureAwait(false);

                if (existingContext != null)
                {
                    existingContext.TargetFile = transcodingFile;
                    if (existingContext.Stream == null)
                    {
                        existingContext.AssignStream(await GetFileStreamAsync(transcodingFile).ConfigureAwait(false));
                    }
                    if (existingContext.CurrentDuration.TotalSeconds == 0)
                    {
                        double bitrate = 0;
                        if (video.TargetVideoBitrate.HasValue && video.TargetAudioBitrate.HasValue)
                        {
                            bitrate = video.TargetVideoBitrate.Value + video.TargetAudioBitrate.Value;
                        }
                        else if (video.SourceVideoStream.Bitrate.HasValue && video.SourceAudioStreams.Any(a => a.Bitrate > 0))
                        {
                            bitrate = video.SourceVideoStream.Bitrate.Value + video.SourceAudioStreams.Max(a => a.Bitrate ?? 0);
                        }
                        bitrate *= 1024; //Bitrate in bits/s
                        if (bitrate > 0)
                        {
                            long startByte = Convert.ToInt64((bitrate * timeStart) / 8.0);
                            if (existingContext.Stream.Length > startByte)
                            {
                                return(existingContext);
                            }
                        }
                    }
                    else
                    {
                        if (existingContext.CurrentDuration.TotalSeconds > timeStart)
                        {
                            return(existingContext);
                        }
                    }
                }
                else
                {
                    //Presume that it is a cached file
                    TouchFile(transcodingFile);
                    context.Partial    = false;
                    context.TargetFile = transcodingFile;
                    context.AssignStream(await GetFileStreamAsync(transcodingFile).ConfigureAwait(false));
                    return(context);
                }
            }

            if (video.TargetVideoContainer == VideoContainer.Hls)
            {
                long requestedSegmentSequence = requestedSegmentSequence = Convert.ToInt64(timeStart / HLSSegmentTimeInSeconds);
                if (requestedSegmentSequence > 0)
                {
                    requestedSegmentSequence--; //1 segment file margin
                }
                string pathName    = FFMpegPlaylistManifest.GetPlaylistFolderFromTranscodeFile(_cachePath, transcodingFile);
                string playlist    = Path.Combine(pathName, PlaylistManifest.PLAYLIST_MANIFEST_FILE_NAME);
                string segmentFile = Path.Combine(pathName, requestedSegmentSequence.ToString("00000") + ".ts");
                if (File.Exists(playlist) == true && File.Exists(segmentFile) == true)
                {
                    //Use exisitng context if possible
                    TranscodeContext existingContext = await GetExistingTranscodeContextAsync(clientId, video.TranscodeId).ConfigureAwait(false);

                    if (existingContext != null)
                    {
                        if (existingContext.LastSegment > requestedSegmentSequence)
                        {
                            existingContext.TargetFile = playlist;
                            existingContext.SegmentDir = pathName;
                            if (existingContext.Stream == null)
                            {
                                existingContext.AssignStream(await GetFileStreamAsync(playlist).ConfigureAwait(false));
                            }
                            existingContext.HlsBaseUrl = video.HlsBaseUrl;
                            return(existingContext);
                        }
                    }
                    else
                    {
                        //Presume that it is a cached file
                        TouchDirectory(pathName);
                        context.Partial    = false;
                        context.TargetFile = playlist;
                        context.SegmentDir = pathName;
                        context.HlsBaseUrl = video.HlsBaseUrl;
                        context.AssignStream(await GetFileStreamAsync(playlist).ConfigureAwait(false));
                        return(context);
                    }
                }
            }

            FFMpegTranscodeData data = new FFMpegTranscodeData(_cachePath)
            {
                TranscodeId = video.TranscodeId, ClientId = clientId
            };

            if (string.IsNullOrEmpty(video.TranscoderBinPath) == false)
            {
                data.TranscoderBinPath = video.TranscoderBinPath;
            }
            if (string.IsNullOrEmpty(video.TranscoderArguments) == false)
            {
                data.ConcatedFileInput   = video.ConcatSourceMediaPaths;
                data.TranscoderArguments = video.TranscoderArguments;
                data.InputMediaFilePaths = video.SourceMediaPaths;
                if (video.PreferredSourceSubtitles != null)
                {
                    foreach (var mediaSourceIndex in video.PreferredSourceSubtitles.Keys)
                    {
                        foreach (var sub in video.PreferredSourceSubtitles[mediaSourceIndex])
                        {
                            if (string.IsNullOrEmpty(sub.SourcePath) == false)
                            {
                                data.AddSubtitle(mediaSourceIndex, sub.SourcePath);
                                context.TargetSubtitles.Add(sub.SourcePath);
                            }
                        }
                    }
                }
                data.OutputFilePath = transcodingFile;
                context.TargetFile  = transcodingFile;
            }
            else
            {
                data.Encoder = _ffMpegEncoderHandler.StartEncoding(video.TranscodeId, video.TargetVideoCodec);
                _ffMpegCommandline.InitTranscodingParameters(video.ConcatSourceMediaPaths, video.SourceMediaPaths, ref data);

                bool useX26XLib = video.TargetVideoCodec == VideoCodec.H264 || video.TargetVideoCodec == VideoCodec.H265;
                _ffMpegCommandline.AddTranscodingThreadsParameters(!useX26XLib, ref data);

                int subCopyStream = -1;
                if (video.PreferredSourceSubtitles.Any())
                {
                    if (video.FirstPreferredSourceSubtitle.IsEmbedded)
                    {
                        subCopyStream = video.FirstPreferredSourceSubtitle.StreamIndex;
                        _ffMpegCommandline.AddSubtitleCopyParameters(video.FirstPreferredSourceSubtitle, data);
                    }
                    else if (embeddedSupported)
                    {
                        foreach (int mediaSourceIndex in video.PreferredSourceSubtitles.Keys)
                        {
                            _ffMpegCommandline.AddSubtitleEmbeddingParameters(mediaSourceIndex, video.PreferredSourceSubtitles[mediaSourceIndex], embeddedSubCodec, timeStart, data);
                        }
                    }
                    else if (video.TargetSubtitleSupport != SubtitleSupport.SoftCoded)
                    {
                        video.TargetSubtitleSupport = SubtitleSupport.HardCoded; //Fallback to hardcoded subtitles
                        _logger.Debug("FFMpegMediaConverter: Soft subs not supported. Fallback to hardcoded subtitles");
                    }
                }
                else
                {
                    embeddedSupported = false;
                    data.OutputArguments.Add("-sn");
                }

                _ffMpegCommandline.AddTimeParameters(video, timeStart, timeDuration, data);
                _ffMpegCommandline.AddStreamMapParameters(video, data);

                FFMpegEncoderConfig encoderConfig = _ffMpegEncoderHandler.GetEncoderConfig(data.Encoder);
                _ffMpegCommandline.AddVideoParameters(video, data.TranscodeId, encoderConfig, data);
                _ffMpegCommandline.AddVideoAudioParameters(video, data);

                var result = await _ffMpegCommandline.AddTargetVideoFormatAndOutputFileParametersAsync(video, transcodingFile, timeStart, data).ConfigureAwait(false);

                context.TargetFile     = result.TranscodingFile;
                context.CurrentSegment = result.StartSegment;
                if (video.PreferredSourceSubtitles.Any())
                {
                    foreach (var sub in video.PreferredSourceSubtitles.SelectMany(s => s.Value))
                    {
                        if (string.IsNullOrEmpty(sub.SourcePath) == false)
                        {
                            context.TargetSubtitles.Add(sub.SourcePath);
                        }
                    }
                }
            }

            _logger.Info("FFMpegMediaConverter: Invoking transcoder to transcode video file '{0}' for transcode '{1}' with arguments '{2}'", video.SourceMediaPaths.First().Value, video.TranscodeId, String.Join(", ", data.OutputArguments.ToArray()));
            context.Start();
            context.AssignStream(await ExecuteTranscodingProcessAsync(data, context, waitForBuffer).ConfigureAwait(false));
            return(context);
        }
Пример #14
0
 /// <summary>
 ///     Add subtitle to file. It will be added as new stream so if you want to burn subtitles into video you should use
 ///     BurnSubtitle method.
 /// </summary>
 /// <param name="inputPath">Input path</param>
 /// <param name="outputPath">Output path</param>
 /// <param name="subtitlePath">Path to subtitle file in .srt format</param>
 /// <param name="subtitleCodec">The Subtitle Codec to Use to Encode the Subtitles</param>
 /// <param name="language">Language code in ISO 639. Example: "eng", "pol", "pl", "de", "ger"</param>
 /// <returns>Conversion result</returns>
 public async Task <IConversion> AddSubtitle(string inputPath, string outputPath, string subtitlePath, SubtitleCodec subtitleCodec, string language = null)
 {
     return(await Task.FromResult(Conversion.AddSubtitle(inputPath, outputPath, subtitlePath, subtitleCodec, language)));
 }
Пример #15
0
        public static IConversion Transcode(string inputFilePath, string outputFilePath, VideoCodec videoCodec, AudioCodec audioCodec, SubtitleCodec subtitleCodec, bool keepSubtitles = false)
        {
            IMediaInfo info = FFmpeg.GetMediaInfo(inputFilePath).GetAwaiter().GetResult();

            var conversion = New().SetOutput(outputFilePath);

            foreach (var stream in info.Streams)
            {
                if (stream is IVideoStream videoStream)
                {
                    // PR #268 We have to force the framerate here due to an FFmpeg bug with videos > 100fps from android devices
                    conversion.AddStream(videoStream.SetCodec(videoCodec).SetFramerate(videoStream.Framerate));
                }
                else if (stream is IAudioStream audioStream)
                {
                    conversion.AddStream(audioStream.SetCodec(audioCodec));
                }
                else if (stream is ISubtitleStream subtitleStream && keepSubtitles)
                {
                    conversion.AddStream(subtitleStream.SetCodec(subtitleCodec));
                }
            }

            return(conversion);
        }
Пример #16
0
 /// <inheritdoc />
 public ISubtitleStream SetCodec(SubtitleCodec codec)
 {
     return(SetCodec(codec.ToString()));
 }
Пример #17
0
        /// <summary>
        ///     Add subtitle to file. It will be added as new stream so if you want to burn subtitles into video you should use
        ///     SetSubtitles method.
        /// </summary>
        /// <param name="inputPath">Input path</param>
        /// <param name="outputPath">Output path</param>
        /// <param name="subtitlePath">Path to subtitle file in .srt format</param>
        /// <param name="subtitleCodec">The Subtitle Codec to Use to Encode the Subtitles</param>
        /// <param name="language">Language code in ISO 639. Example: "eng", "pol", "pl", "de", "ger"</param>
        /// <returns>Conversion result</returns>
        internal static IConversion AddSubtitle(string inputPath, string outputPath, string subtitlePath, SubtitleCodec subtitleCodec, string language = null)
        {
            IMediaInfo mediaInfo    = FFmpeg.GetMediaInfo(inputPath).GetAwaiter().GetResult();
            IMediaInfo subtitleInfo = FFmpeg.GetMediaInfo(subtitlePath).GetAwaiter().GetResult();

            ISubtitleStream subtitleStream = subtitleInfo.SubtitleStreams.First()
                                             .SetLanguage(language);

            return(New()
                   .AddStream(mediaInfo.VideoStreams)
                   .AddStream(mediaInfo.AudioStreams)
                   .AddStream(subtitleStream.SetCodec(subtitleCodec))
                   .SetOutput(outputPath));
        }
Пример #18
0
 private static bool TryGetCodec(string source, out SubtitleCodec result)
 {
     return(SubtitleCodecs.TryGetValue(source.ToUpper(), out result));
 }
Пример #19
0
        public async Task BasicTranscode_InputFileWithSubtitles_SkipSubtitles(VideoCodec videoCodec, AudioCodec audioCodec, SubtitleCodec subtitleCodec)
        {
            string output = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + FileExtensions.Mp4);

            IConversionResult result = await(await FFmpeg.Conversions.FromSnippet.Transcode(Resources.MkvWithSubtitles, output, videoCodec, audioCodec, subtitleCodec)).Start();


            IMediaInfo mediaInfo = await FFmpeg.GetMediaInfo(output);

            Assert.Equal(TimeSpan.FromSeconds(9), mediaInfo.Duration);
            Assert.Single(mediaInfo.VideoStreams);
            Assert.Single(mediaInfo.AudioStreams);
            Assert.Empty(mediaInfo.SubtitleStreams);
            IAudioStream audioStream = mediaInfo.AudioStreams.First();
            IVideoStream videoStream = mediaInfo.VideoStreams.First();

            Assert.NotNull(videoStream);
            Assert.NotNull(audioStream);
            Assert.Equal(videoCodec.ToString(), videoStream.Codec);
            Assert.Equal(audioCodec.ToString(), audioStream.Codec);
            Assert.Equal(25, videoStream.Framerate);
        }
Пример #20
0
 /// <summary>
 ///     Transcode one file to another with destination format and codecs.
 /// </summary>
 /// <param name="inputFilePath">Path to file</param>
 /// <param name="outputFilePath">Path to file</param>
 /// <param name="audioCodec"> The Audio Codec to Transcode the input to</param>
 /// <param name="videoCodec"> The Video Codec to Transcode the input to</param>
 /// <param name="videoCodec"> The Subtitle Codec to Transcode the input to</param>
 /// <param name="keepSubtitles">Whether to Keep Subtitles in the output video</param>
 /// <returns>IConversion object</returns>
 public async Task <IConversion> Transcode(string inputFilePath, string outputFilePath, VideoCodec videoCodec, AudioCodec audioCodec, SubtitleCodec subtitleCodec, bool keepSubtitles = false)
 {
     return(await Task.FromResult(Conversion.Transcode(inputFilePath, outputFilePath, videoCodec, audioCodec, subtitleCodec, keepSubtitles)));
 }
        protected override async Task <bool> ConvertSubtitleFileAsync(string clientId, VideoTranscoding video, double timeStart, string transcodingFile, SubtitleStream sourceSubtitle, SubtitleStream res)
        {
            SubtitleCodec targetCodec = video.TargetSubtitleCodec;

            if (targetCodec == SubtitleCodec.Unknown)
            {
                targetCodec = sourceSubtitle.Codec;
            }

            string tempFile          = null;
            FFMpegTranscodeData data = new FFMpegTranscodeData(_cachePath)
            {
                TranscodeId = video.TranscodeId + "_sub", ClientId = clientId
            };

            if (string.IsNullOrEmpty(video.TranscoderBinPath) == false)
            {
                data.TranscoderBinPath = video.TranscoderBinPath;
            }
            if (string.IsNullOrEmpty(video.TranscoderArguments) == false)
            {
                // TODO: not sure if this is working
                data.TranscoderArguments = video.TranscoderArguments;
                data.InputMediaFilePaths.Add(0, res.SourcePath);
                data.InputArguments.Add(0, new List <string>());
            }
            else
            {
                tempFile = transcodingFile + ".tmp";
                res      = await ConvertSubtitleEncodingAsync(res, tempFile, video.TargetSubtitleCharacterEncoding).ConfigureAwait(false);

                // TODO: not sure if this is working
                _ffMpegCommandline.InitTranscodingParameters(false, new Dictionary <int, string> {
                    { 0, res.SourcePath }
                }, ref data);
                data.InputArguments[0].Add(string.Format("-f {0}", FFMpegGetSubtitleContainer.GetSubtitleContainer(sourceSubtitle.Codec)));
                if (timeStart > 0)
                {
                    data.OutputArguments.Add(string.Format(CultureInfo.InvariantCulture, "-ss {0:0.0}", timeStart));
                }

                res.Codec = targetCodec;
                string subtitleEncoder = "copy";
                if (res.Codec == SubtitleCodec.Unknown)
                {
                    res.Codec = SubtitleCodec.Ass;
                }

                if (sourceSubtitle.Codec != res.Codec)
                {
                    subtitleEncoder = FFMpegGetSubtitleContainer.GetSubtitleContainer(res.Codec);
                }

                string subtitleFormat = FFMpegGetSubtitleContainer.GetSubtitleContainer(res.Codec);
                data.OutputArguments.Add("-vn");
                data.OutputArguments.Add("-an");
                data.OutputArguments.Add(string.Format("-c:s {0}", subtitleEncoder));
                data.OutputArguments.Add(string.Format("-f {0}", subtitleFormat));
            }
            data.OutputFilePath = transcodingFile;

            _logger.Debug("FFMpegMediaConverter: Invoking transcoder to transcode subtitle file '{0}' for transcode '{1}'", res.SourcePath, data.TranscodeId);
            bool success = false;
            var  path    = ResourcePath.Deserialize(res.SourcePath);

            if (path.TryCreateLocalResourceAccessor(out var subRes))
            {
                using (var rah = new LocalFsResourceAccessorHelper(subRes))
                    using (var access = rah.LocalFsResourceAccessor.EnsureLocalFileSystemAccess())
                    {
                        var result = await FFMpegBinary.FFMpegExecuteWithResourceAccessAsync(rah.LocalFsResourceAccessor, data.TranscoderArguments, ProcessPriorityClass.Normal, _transcoderTimeout).ConfigureAwait(false);

                        success = result.Success;
                    }
            }
            if (success && File.Exists(transcodingFile) == true)
            {
                if (tempFile != null && File.Exists(tempFile))
                {
                    File.Delete(tempFile);
                }
                res.SourcePath = LocalFsResourceProviderBase.ToProviderPath(transcodingFile);
                return(true);
            }
            return(false);
        }