Browse Source

use ffprobe -show_chapters command

Luke Pulverenti 11 years ago
parent
commit
ae248b045a

+ 13 - 3
MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs

@@ -1,5 +1,4 @@
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
+using System.Collections.Generic;
 
 namespace MediaBrowser.Controller.MediaEncoding
 {
@@ -24,7 +23,18 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// Gets or sets the chapters.
         /// </summary>
         /// <value>The chapters.</value>
-        public List<ChapterInfo> Chapters { get; set; }
+        public MediaChapter[] Chapters { get; set; }
+    }
+
+    public class MediaChapter
+    {
+        public int id { get; set; }
+        public string time_base { get; set; }
+        public long start { get; set; }
+        public string start_time { get; set; }
+        public long end { get; set; }
+        public string end_time { get; set; }
+        public Dictionary<string, string> tags { get; set; }
     }
 
     /// <summary>

+ 5 - 1
MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs

@@ -50,12 +50,16 @@ namespace MediaBrowser.Providers.MediaInfo
             return ItemUpdateType.MetadataImport;
         }
 
+        private const string SchemaVersion = "1";
+
         private async Task<InternalMediaInfoResult> GetMediaInfo(BaseItem item, CancellationToken cancellationToken)
         {
             cancellationToken.ThrowIfCancellationRequested();
 
             var idString = item.Id.ToString("N");
-            var cachePath = Path.Combine(_appPaths.CachePath, "ffprobe-audio", idString.Substring(0, 2), idString, "v" + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");
+            var cachePath = Path.Combine(_appPaths.CachePath, 
+                "ffprobe-audio", 
+                idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");
 
             try
             {

+ 25 - 2
MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs

@@ -107,6 +107,8 @@ namespace MediaBrowser.Providers.MediaInfo
             return ItemUpdateType.MetadataImport;
         }
 
+        private const string SchemaVersion = "1";
+
         private async Task<InternalMediaInfoResult> GetMediaInfo(BaseItem item, IIsoMount isoMount, CancellationToken cancellationToken)
         {
             cancellationToken.ThrowIfCancellationRequested();
@@ -114,7 +116,9 @@ namespace MediaBrowser.Providers.MediaInfo
             cancellationToken.ThrowIfCancellationRequested();
 
             var idString = item.Id.ToString("N");
-            var cachePath = Path.Combine(_appPaths.CachePath, "ffprobe-video", idString.Substring(0, 2), idString, "v" + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");
+            var cachePath = Path.Combine(_appPaths.CachePath, 
+                "ffprobe-video",
+                idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");
 
             try
             {
@@ -161,7 +165,8 @@ namespace MediaBrowser.Providers.MediaInfo
 
             var mediaStreams = MediaEncoderHelpers.GetMediaInfo(data).MediaStreams;
 
-            var chapters = data.Chapters ?? new List<ChapterInfo>();
+            var mediaChapters = (data.Chapters ?? new MediaChapter[] { }).ToList();
+            var chapters = mediaChapters.Select(GetChapterInfo).ToList();
 
             if (video.VideoType == VideoType.BluRay || (video.IsoType.HasValue && video.IsoType.Value == IsoType.BluRay))
             {
@@ -200,6 +205,24 @@ namespace MediaBrowser.Providers.MediaInfo
             await _itemRepo.SaveChapters(video.Id, chapters, cancellationToken).ConfigureAwait(false);
         }
 
+        private ChapterInfo GetChapterInfo(MediaChapter chapter)
+        {
+            var info = new ChapterInfo();
+
+            if (chapter.tags != null)
+            {
+                string name;
+                if (chapter.tags.TryGetValue("title", out name))
+                {
+                    info.Name = name;
+                }
+            }
+
+            info.StartPositionTicks = chapter.start/100;
+
+            return info;
+        }
+
         private void FetchBdInfo(BaseItem item, List<ChapterInfo> chapters, List<MediaStream> mediaStreams, BlurayDiscInfo blurayInfo)
         {
             var video = (Video)item;

+ 6 - 84
MediaBrowser.Server.Implementations/MediaEncoder/MediaEncoder.cs

@@ -175,6 +175,10 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
                                                                  string probeSizeArgument,
                                                                  CancellationToken cancellationToken)
         {
+            var args = extractChapters
+                ? "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_chapters -show_format"
+                : "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_format";
+
             var process = new Process
             {
                 StartInfo = new ProcessStartInfo
@@ -186,8 +190,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
                     RedirectStandardOutput = true,
                     RedirectStandardError = true,
                     FileName = FFProbePath,
-                    Arguments = string.Format(
-                            "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_format",
+                    Arguments = string.Format(args,
                             probeSizeArgument, inputPath).Trim(),
 
                     WindowStyle = ProcessWindowStyle.Hidden,
@@ -204,7 +207,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
             await _ffProbeResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
 
             InternalMediaInfoResult result;
-            string standardError = null;
 
             try
             {
@@ -221,24 +223,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
 
             try
             {
-                Task<string> standardErrorReadTask = null;
-
-                // MUST read both stdout and stderr asynchronously or a deadlock may occurr
-                if (extractChapters)
-                {
-                    standardErrorReadTask = process.StandardError.ReadToEndAsync();
-                }
-                else
-                {
-                    process.BeginErrorReadLine();
-                }
+                process.BeginErrorReadLine();
 
                 result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream);
-
-                if (extractChapters)
-                {
-                    standardError = await standardErrorReadTask.ConfigureAwait(false);
-                }
             }
             catch
             {
@@ -282,11 +269,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
                 }
             }
 
-            if (extractChapters && !string.IsNullOrEmpty(standardError))
-            {
-                AddChapters(result, standardError);
-            }
-
             return result;
         }
 
@@ -295,66 +277,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
         /// </summary>
         protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
 
-        /// <summary>
-        /// Adds the chapters.
-        /// </summary>
-        /// <param name="result">The result.</param>
-        /// <param name="standardError">The standard error.</param>
-        private void AddChapters(InternalMediaInfoResult result, string standardError)
-        {
-            var lines = standardError.Split('\n').Select(l => l.TrimStart());
-
-            var chapters = new List<ChapterInfo>();
-
-            ChapterInfo lastChapter = null;
-
-            foreach (var line in lines)
-            {
-                if (line.StartsWith("Chapter", StringComparison.OrdinalIgnoreCase))
-                {
-                    // Example:
-                    // Chapter #0.2: start 400.534, end 4565.435
-                    const string srch = "start ";
-                    var start = line.IndexOf(srch, StringComparison.OrdinalIgnoreCase);
-
-                    if (start == -1)
-                    {
-                        continue;
-                    }
-
-                    var subString = line.Substring(start + srch.Length);
-                    subString = subString.Substring(0, subString.IndexOf(','));
-
-                    double seconds;
-
-                    if (double.TryParse(subString, NumberStyles.Any, UsCulture, out seconds))
-                    {
-                        lastChapter = new ChapterInfo
-                            {
-                                StartPositionTicks = TimeSpan.FromSeconds(seconds).Ticks
-                            };
-
-                        chapters.Add(lastChapter);
-                    }
-                }
-
-                else if (line.StartsWith("title", StringComparison.OrdinalIgnoreCase))
-                {
-                    if (lastChapter != null && string.IsNullOrEmpty(lastChapter.Name))
-                    {
-                        var index = line.IndexOf(':');
-
-                        if (index != -1)
-                        {
-                            lastChapter.Name = line.Substring(index + 1).Trim().TrimEnd('\r');
-                        }
-                    }
-                }
-            }
-
-            result.Chapters = chapters;
-        }
-
         /// <summary>
         /// Processes the exited.
         /// </summary>