public MovieBuilder ReplaceSubtitleStream(SubtitleStream stream)
 {
     _movie.SubtitleStreams = new List <SubtitleStream> {
         stream
     };
     return(this);
 }
Exemple #2
0
        private void OnVideoFound(object sender, EventArgs args)
        {
            var videoFile = (args as VideoFoundEventArgs).VideoFile;

            try
            {
                using (FileStream videoStream = File.OpenRead(videoFile.FullName))
                {
                    SubtitleStream subtitleStream = DownloadSubtitle(videoStream);

                    if (subtitleStream != null)
                    {
                        using (var subFileStream = subtitleStream.Stream)
                        {
                            SubtitleInfo subtitleFile = subtitleStream.WriteToFile(new FileInfo(Path.ChangeExtension(videoFile.FullName, subtitleStream.Format.Extension)));

                            if (subtitleFile != null)
                            {
                                SubtitleDownloaded(SubtitleDownloaded.Target, new SubtitleDownloadedEventArgs(videoFile, subtitleFile));
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                // File not ready (e.g.: still being downloaded/copied/etc)
            }

            CurrentJobs.Remove(videoFile.FullName);
        }
Exemple #3
0
        SubtitleStream IPluginSubtitles.OpenSubtitles(SubtitleStream stream)
        {
            if (stream.Tag == null || !(stream.Tag is OpenSubtitlesJson))
            {
                return(null);
            }

            return((SubtitleStream)stream);
        }
Exemple #4
0
 public SubtitleStreamBuilder(string language)
 {
     _stream = new SubtitleStream
     {
         Language     = language,
         Codec        = "codec",
         DisplayTitle = language,
         Id           = Guid.NewGuid().ToString(),
         IsDefault    = false
     };
 }
Exemple #5
0
        private SubtitleStream ParseSubtitleStream(JToken token)
        {
            SubtitleStream stream =
                new SubtitleStream(ParseBaseStream(token))
            {
                Duration   = ParseTimeSpan(token["duration"].Value <string>()),
                DurationTs = token["duration_ts"].Value <int?>() ?? -1
            };

            return(stream);
        }
Exemple #6
0
        public SubtitleStream OpenSubtitles(SubtitleStream stream)
        {
            foreach (var sstream in SubtitleStreams)
            {
                if (sstream.Tag == stream.Tag)
                {
                    return(stream);
                }
            }

            return(null);
        }
Exemple #7
0
        public SubtitleStream OpenSubtitles(SubtitleStream stream)
        {
            if (stream.DecoderInput.StreamIndex == -1)
            {
                return(null);
            }

            foreach (var sstream in SubtitleStreams)
            {
                if (sstream.DecoderInput.StreamIndex == stream.DecoderInput.StreamIndex)
                {
                    return(sstream);
                }
            }

            return(null);
        }
Exemple #8
0
        public bool Download(SubtitleStream stream)
        {
            if (stream.Tag == null || !(stream.Tag is OpenSubtitlesJson))
            {
                return(false);
            }

            var sub = (OpenSubtitlesJson)stream.Tag;

            if (sub.Download() != 0)
            {
                return(false);
            }

            stream.DecoderInput.Url = sub.AvailableAt;

            return(true);
        }
        internal static void ParseStreamSubtitleLine(IResourceAccessor file, string streamSubtitleLine, ref MetadataContainer info, Dictionary <string, CultureInfo> countryCodesMapping)
        {
            streamSubtitleLine = streamSubtitleLine.Trim();

            SubtitleStream sub   = new SubtitleStream();
            Match          match = Regex.Match(streamSubtitleLine, @"#[\d][\.:](?<stream>[\d]{1,2}).*\((?<lang>(\w+))\)[\.:]", RegexOptions.IgnoreCase);

            if (match.Success)
            {
                sub.StreamIndex = Convert.ToInt32(match.Groups["stream"].Value.Trim());
                if (match.Groups.Count == 4)
                {
                    string lang = match.Groups["lang"].Value.Trim().ToUpperInvariant();
                    if (countryCodesMapping.ContainsKey(lang))
                    {
                        sub.Language = countryCodesMapping[lang].TwoLetterISOLanguageName.ToUpperInvariant();
                    }
                }
            }
            else
            {
                match = Regex.Match(streamSubtitleLine, @"#[\d][\.:](?<stream>[\d]{1,2}).*[\.:]", RegexOptions.IgnoreCase);
                if (match.Success)
                {
                    sub.StreamIndex = Convert.ToInt32(match.Groups["stream"].Value.Trim());
                }
            }

            string codecValue = streamSubtitleLine.Substring(streamSubtitleLine.IndexOf("Subtitle: ", StringComparison.InvariantCultureIgnoreCase) + 10).Split(' ')[0];

            sub.Codec   = FFMpegParseSubtitleCodec.ParseSubtitleCodec(codecValue);
            sub.Default = streamSubtitleLine.IndexOf("(default)", StringComparison.InvariantCultureIgnoreCase) > -1;
            if (!info.Subtitles[Editions.DEFAULT_EDITION].ContainsKey(0))
            {
                info.Subtitles[Editions.DEFAULT_EDITION].Add(0, new List <SubtitleStream>());
            }
            info.Subtitles[Editions.DEFAULT_EDITION][0].Add(sub);
        }
Exemple #10
0
 public bool Download(SubtitleStream stream)
 {
     return(true);
 }
 public MovieBuilder AddSubtitleStream(SubtitleStream stream)
 {
     _movie.SubtitleStreams.Add(stream);
     return(this);
 }
Exemple #12
0
        public static Task <Stream> CreatePlaylistManifestAsync(VideoTranscoding video, SubtitleStream sub)
        {
            if (ServiceRegistration.IsRegistered <IMediaConverter>())
            {
                IMediaConverter         converter = ServiceRegistration.Get <IMediaConverter>();
                TranscodedVideoMetadata metaData  = converter.GetTranscodedVideoMetadata(video);

                double bitrate = 10000000;
                if (metaData.TargetVideoBitrate.HasValue && metaData.TargetAudioBitrate.HasValue)
                {
                    bitrate += metaData.TargetVideoBitrate.Value;
                    bitrate += metaData.TargetAudioBitrate.Value;
                    bitrate  = bitrate * 1024; //Bitrate in bits/s
                }

                int width  = 1920;
                int height = 1080;
                if (metaData.TargetVideoMaxHeight.HasValue && metaData.TargetVideoMaxWidth.HasValue)
                {
                    width  = metaData.TargetVideoMaxHeight.Value;
                    height = metaData.TargetVideoMaxWidth.Value;
                }

                string codec = "avc1.66.30,mp4a.40.2"; //H264 Baseline 3.0 and AAC
                if (metaData.TargetVideoCodec == VideoCodec.H264)
                {
                    codec = "avc1.";
                    if (metaData.TargetProfile == EncodingProfile.Baseline)
                    {
                        codec += "66.";
                    }
                    else if (metaData.TargetProfile == EncodingProfile.Main)
                    {
                        codec += "77.";
                    }
                    else //High
                    {
                        codec += "100.";
                    }
                    codec += ((metaData.TargetLevel ?? 0) * 10).ToString("0");

                    if (metaData.TargetAudioCodec == AudioCodec.Ac3)
                    {
                        codec += ",ac-3";
                    }
                    else
                    {
                        codec += ",mp4a.40.";
                        if (metaData.TargetAudioCodec == AudioCodec.Aac)
                        {
                            codec += "2";
                        }
                        else if (metaData.TargetAudioCodec == AudioCodec.Mp3)
                        {
                            codec += "34";
                        }
                        else //HE-ACC
                        {
                            codec += "5";
                        }
                    }
                }

                StringBuilder manifestBuilder = new StringBuilder();
                using (StringWriter writer = new StringWriter(manifestBuilder))
                {
                    writer.WriteLine("#EXTM3U");
                    writer.WriteLine();
                    if (sub != null)
                    {
                        CultureInfo culture = new CultureInfo(sub.Language);
                        writer.WriteLine(string.Format("#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"{0}\",DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE=\"{1}\",URI=\"{2}\"",
                                                       culture.DisplayName, culture.TwoLetterISOLanguageName.ToLowerInvariant(), URL_PLACEHOLDER + converter.HLSSubtitlePlayListName));
                        writer.WriteLine();
                    }
                    writer.WriteLine(string.Format("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH={0},RESOLUTION={1},CODECS=\"{2}\"{3}",
                                                   bitrate.ToString("0"), width + "x" + height, codec, sub != null ? ",SUBTITLES=\"subs\"" : ""));
                    writer.WriteLine(URL_PLACEHOLDER + converter.HLSMediaPlayListName);
                    writer.WriteLine();
                }

                var memStream = new MemoryStream(Encoding.UTF8.GetBytes(manifestBuilder.ToString()));
                memStream.Position = 0;
                return(Task.FromResult <Stream>(memStream));
            }
            return(Task.FromResult <Stream>(null));
        }
Exemple #13
0
        /// <summary>
        /// Global Json parser manager
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        internal MovieInfo ReadJson(string json)
        {
            MovieInfo movieInfo   = new MovieInfo();
            JObject   movieObject = JObject.Parse(json);

            if (movieObject["streams"] == null)
            {
                Console.WriteLine("ERROR: No streams found because collection is null");
            }
            else
            {
                foreach (JToken token in movieObject["streams"])
                {
                    try
                    {
                        if (token["codec_type"] == null)
                        {
                            Console.WriteLine("ERROR: Stream skipped because its null");
                            continue;
                        }

                        if (token["codec_type"].Value <string>().Equals("video", StringComparison.OrdinalIgnoreCase))
                        {
                            VideoStream stream = ParseVideoStream(token);
                            movieInfo.VideoStreams.Add(stream);
                        }
                        else if (token["codec_type"].Value <string>().Equals("audio", StringComparison.OrdinalIgnoreCase))
                        {
                            AudioStream stream = ParseAudioStream(token);
                            movieInfo.AudioStreams.Add(stream);
                        }
                        else if (token["codec_type"].Value <string>().Equals("subtitle", StringComparison.OrdinalIgnoreCase))
                        {
                            SubtitleStream stream = ParseSubtitleStream(token);
                            movieInfo.SubtitleStreams.Add(stream);
                        }
                        else
                        {
                            Console.WriteLine("ERROR: Unknown StreamType found: " + token["codec_type"].Value <string>());
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("ERROR: Unhandled Exception in processing stream");
                        Console.WriteLine(ex.Message);
                        Console.WriteLine(ex.Source);
                        Console.WriteLine(ex.StackTrace);
                    }
                }
            }

            if (movieObject["chapters"] == null)
            {
                Console.WriteLine("ERROR: No chapters found because collection is null");
            }
            else
            {
                foreach (JToken token in movieObject["chapters"])
                {
                    try
                    {
                        if (token == null)
                        {
                            Console.WriteLine("ERROR: Chapter skipped because its null");
                            continue;
                        }

                        Chapter chapter = ParseChapter(token);
                        movieInfo.Chapters.Add(chapter);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("ERROR: Unhandled Exception in processing chapters");
                        Console.WriteLine(ex.Message);
                        Console.WriteLine(ex.Source);
                        Console.WriteLine(ex.StackTrace);
                    }
                }
            }

            return(movieInfo);
        }
        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);
        }
 protected override Task <bool> ExtractSubtitleFileAsync(int sourceMediaIndex, VideoTranscoding video, SubtitleStream subtitle, string subtitleEncoding, string targetFilePath, double timeStart)
 {
     return(_ffMpegCommandline.ExtractSubtitleFileAsync(sourceMediaIndex, video, subtitle, subtitleEncoding, targetFilePath, timeStart));
 }
Exemple #16
0
        private MovieInfo ConvertCoreObject(CoreRoot core)
        {
            MovieInfo movieInfo = new MovieInfo();

            if (core.Streams != null && core.Streams.Any())
            {
                foreach (CoreStream coreStream in core.Streams)
                {
                    try
                    {
                        BaseStream baseStream = GenerateBaseStream(coreStream);

                        switch (baseStream.StreamType)
                        {
                        case StreamType.None:
                            break;

                        case StreamType.Subtitle:
                            SubtitleStream subtitleStream = new SubtitleStream(baseStream);
                            subtitleStream.Duration   = ParseTimeSpan(coreStream.Duration);
                            subtitleStream.DurationTs = coreStream.DurationTs;
                            movieInfo.SubtitleStreams.Add(subtitleStream);
                            break;

                        case StreamType.Audio:
                            AudioStream audioStream = GenerateAudioStream(baseStream, coreStream);
                            movieInfo.AudioStreams.Add(audioStream);
                            break;

                        case StreamType.Video:
                            VideoStream videoStream = GenerateVideoStream(baseStream, coreStream);
                            movieInfo.VideoStreams.Add(videoStream);
                            break;

                        case StreamType.Data:
                            DataStream dataStream = new DataStream();
                            movieInfo.DataStreams.Add(dataStream);
                            break;

                        case StreamType.Attachment:
                            AttachmentStream attachmentStream = new AttachmentStream();
                            movieInfo.AttachmentStreams.Add(attachmentStream);
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("ERROR: Unhandled Exception while parsing streams:");
                        Console.WriteLine(ex.Message);
                        Console.WriteLine(ex.Source);
                        Console.WriteLine(ex.StackTrace);
                    }
                }
            }

            if (core.Chapters != null && core.Chapters.Any())
            {
                foreach (CoreChapter coreChapter in core.Chapters)
                {
                    try
                    {
                        Chapter chapter = new Chapter();
                        chapter.Id        = coreChapter.Id;
                        chapter.End       = coreChapter.End;
                        chapter.Start     = coreChapter.Start;
                        chapter.TimeBase  = coreChapter.TimeBase;
                        chapter.Tags      = coreChapter.Tags;
                        chapter.StartTime = ParseTimeSpan(coreChapter.StartTime);
                        chapter.EndTime   = ParseTimeSpan(coreChapter.EndTime);

                        if (coreChapter.Tags != null && coreChapter.Tags.Any())
                        {
                            if (coreChapter.Tags.ContainsKey("title"))
                            {
                                chapter.Title = coreChapter.Tags
                                                .FirstOrDefault(x => x.Key.Equals("title", StringComparison.OrdinalIgnoreCase)).Value;
                            }
                        }
                        movieInfo.Chapters.Add(chapter);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("ERROR: Unhandled Exception while parsing streams:");
                        Console.WriteLine(ex.Message);
                        Console.WriteLine(ex.Source);
                        Console.WriteLine(ex.StackTrace);
                    }
                }
            }

            return(movieInfo);
        }