change chapter image location and cleanup dead files
This commit is contained in:
parent
17c4a8461f
commit
d8ce4141ff
|
@ -115,6 +115,11 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <returns>Task.</returns>
|
||||
Task ValidateMediaLibrary(IProgress<double> progress, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Queues the library scan.
|
||||
/// </summary>
|
||||
void QueueLibraryScan();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default view.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
using MediaBrowser.Common.IO;
|
||||
using System.Globalization;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
@ -19,18 +20,6 @@ namespace MediaBrowser.Controller.MediaInfo
|
|||
/// </summary>
|
||||
public class FFMpegManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the video image cache.
|
||||
/// </summary>
|
||||
/// <value>The video image cache.</value>
|
||||
internal FileSystemRepository VideoImageCache { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the subtitle cache.
|
||||
/// </summary>
|
||||
/// <value>The subtitle cache.</value>
|
||||
internal FileSystemRepository SubtitleCache { get; set; }
|
||||
|
||||
private readonly IServerApplicationPaths _appPaths;
|
||||
private readonly IMediaEncoder _encoder;
|
||||
private readonly ILogger _logger;
|
||||
|
@ -53,32 +42,17 @@ namespace MediaBrowser.Controller.MediaInfo
|
|||
_logger = logger;
|
||||
_itemRepo = itemRepo;
|
||||
_fileSystem = fileSystem;
|
||||
|
||||
VideoImageCache = new FileSystemRepository(VideoImagesDataPath);
|
||||
SubtitleCache = new FileSystemRepository(SubtitleCachePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the video images data path.
|
||||
/// Gets the chapter images data path.
|
||||
/// </summary>
|
||||
/// <value>The video images data path.</value>
|
||||
public string VideoImagesDataPath
|
||||
/// <value>The chapter images data path.</value>
|
||||
public string ChapterImagesPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(_appPaths.DataPath, "extracted-video-images");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the audio images data path.
|
||||
/// </summary>
|
||||
/// <value>The audio images data path.</value>
|
||||
public string AudioImagesDataPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(_appPaths.DataPath, "extracted-audio-images");
|
||||
return Path.Combine(_appPaths.DataPath, "chapter-images");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +60,7 @@ namespace MediaBrowser.Controller.MediaInfo
|
|||
/// Gets the subtitle cache path.
|
||||
/// </summary>
|
||||
/// <value>The subtitle cache path.</value>
|
||||
public string SubtitleCachePath
|
||||
private string SubtitleCachePath
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -122,6 +96,8 @@ namespace MediaBrowser.Controller.MediaInfo
|
|||
|
||||
var runtimeTicks = video.RunTimeTicks ?? 0;
|
||||
|
||||
var currentImages = GetSavedChapterImages(video);
|
||||
|
||||
foreach (var chapter in chapters)
|
||||
{
|
||||
if (chapter.StartPositionTicks >= runtimeTicks)
|
||||
|
@ -130,11 +106,9 @@ namespace MediaBrowser.Controller.MediaInfo
|
|||
break;
|
||||
}
|
||||
|
||||
var filename = video.Path + "_" + video.DateModified.Ticks + "_" + chapter.StartPositionTicks;
|
||||
var path = GetChapterImagePath(video, chapter.StartPositionTicks);
|
||||
|
||||
var path = VideoImageCache.GetResourcePath(filename, ".jpg");
|
||||
|
||||
if (!File.Exists(path))
|
||||
if (!currentImages.Contains(path, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
if (extractImages)
|
||||
{
|
||||
|
@ -188,9 +162,35 @@ namespace MediaBrowser.Controller.MediaInfo
|
|||
await _itemRepo.SaveChapters(video.Id, chapters, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
DeleteDeadImages(currentImages, chapters);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private void DeleteDeadImages(IEnumerable<string> images, IEnumerable<ChapterInfo> chapters)
|
||||
{
|
||||
var deadImages = images
|
||||
.Except(chapters.Select(i => i.ImagePath), StringComparer.OrdinalIgnoreCase)
|
||||
.Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i), StringComparer.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
|
||||
foreach (var image in deadImages)
|
||||
{
|
||||
_logger.Debug("Deleting dead chapter image {0}", image);
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(image);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.ErrorException("Error deleting {0}.", ex, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the subtitle cache path.
|
||||
/// </summary>
|
||||
|
@ -220,7 +220,39 @@ namespace MediaBrowser.Controller.MediaInfo
|
|||
ticksParam += _fileSystem.GetLastWriteTimeUtc(stream.Path).Ticks;
|
||||
}
|
||||
|
||||
return SubtitleCache.GetResourcePath(input.Id + "_" + subtitleStreamIndex + "_" + input.DateModified.Ticks + ticksParam, outputExtension);
|
||||
var filename = (input.Id + "_" + subtitleStreamIndex.ToString(UsCulture) + "_" + input.DateModified.Ticks.ToString(UsCulture) + ticksParam).GetMD5() + outputExtension;
|
||||
|
||||
var prefix = filename.Substring(0, 1);
|
||||
|
||||
return Path.Combine(SubtitleCachePath, prefix, filename);
|
||||
}
|
||||
|
||||
public string GetChapterImagePath(Video video, long chapterPositionTicks)
|
||||
{
|
||||
var filename = video.DateModified.Ticks.ToString(UsCulture) + "_" + chapterPositionTicks.ToString(UsCulture) + ".jpg";
|
||||
|
||||
var videoId = video.Id.ToString();
|
||||
var prefix = videoId.Substring(0, 1);
|
||||
|
||||
return Path.Combine(ChapterImagesPath, prefix, videoId, filename);
|
||||
}
|
||||
|
||||
public List<string> GetSavedChapterImages(Video video)
|
||||
{
|
||||
var videoId = video.Id.ToString();
|
||||
var prefix = videoId.Substring(0, 1);
|
||||
|
||||
var path = Path.Combine(ChapterImagesPath, prefix, videoId);
|
||||
|
||||
try
|
||||
{
|
||||
return Directory.EnumerateFiles(path)
|
||||
.ToList();
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
|
@ -22,12 +21,6 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
/// </summary>
|
||||
public class AudioImageProvider : BaseMetadataProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the image cache.
|
||||
/// </summary>
|
||||
/// <value>The image cache.</value>
|
||||
public FileSystemRepository ImageCache { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The _locks
|
||||
/// </summary>
|
||||
|
@ -48,8 +41,6 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
: base(logManager, configurationManager)
|
||||
{
|
||||
_mediaEncoder = mediaEncoder;
|
||||
|
||||
ImageCache = new FileSystemRepository(Kernel.Instance.FFMpegManager.AudioImagesDataPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -113,7 +104,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
return ItemUpdateType.ImageUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Fetches metadata and returns true or false indicating if any work that requires persistence was done
|
||||
/// </summary>
|
||||
|
@ -154,13 +145,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var album = item.Parent as MusicAlbum;
|
||||
|
||||
var filename = item.Album ?? string.Empty;
|
||||
filename += item.Artists.FirstOrDefault() ?? string.Empty;
|
||||
filename += album == null ? item.Id.ToString("N") + item.DateModified.Ticks : album.Id.ToString("N") + album.DateModified.Ticks;
|
||||
|
||||
var path = ImageCache.GetResourcePath(filename + "_primary", ".jpg");
|
||||
var path = GetAudioImagePath(item);
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
|
@ -195,6 +180,38 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
item.PrimaryImagePath = path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the audio image path.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private string GetAudioImagePath(Audio item)
|
||||
{
|
||||
var album = item.Parent as MusicAlbum;
|
||||
|
||||
var filename = item.Album ?? string.Empty;
|
||||
filename += item.Artists.FirstOrDefault() ?? string.Empty;
|
||||
filename += album == null ? item.Id.ToString("N") + item.DateModified.Ticks : album.Id.ToString("N") + album.DateModified.Ticks + "_primary";
|
||||
|
||||
filename = filename.GetMD5() + ".jpg";
|
||||
|
||||
var prefix = filename.Substring(0, 1);
|
||||
|
||||
return Path.Combine(AudioImagesPath, prefix, filename);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the audio images data path.
|
||||
/// </summary>
|
||||
/// <value>The audio images data path.</value>
|
||||
public string AudioImagesPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(ConfigurationManager.ApplicationPaths.DataPath, "extracted-audio-images");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lock.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
|
@ -12,7 +11,6 @@ using MediaBrowser.Model.Logging;
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -20,12 +18,6 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
{
|
||||
class VideoImageProvider : BaseMetadataProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the image cache.
|
||||
/// </summary>
|
||||
/// <value>The image cache.</value>
|
||||
public FileSystemRepository ImageCache { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The _locks
|
||||
/// </summary>
|
||||
|
@ -42,8 +34,6 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
{
|
||||
_mediaEncoder = mediaEncoder;
|
||||
_isoManager = isoManager;
|
||||
|
||||
ImageCache = new FileSystemRepository(Kernel.Instance.FFMpegManager.VideoImagesDataPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -206,9 +196,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var filename = item.Path + "_" + item.DateModified.Ticks + "_primary";
|
||||
|
||||
var path = ImageCache.GetResourcePath(filename, ".jpg");
|
||||
var path = GetVideoImagePath(item);
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
|
@ -310,5 +298,33 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||
{
|
||||
return _locks.GetOrAdd(filename, key => new SemaphoreSlim(1, 1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the video images data path.
|
||||
/// </summary>
|
||||
/// <value>The video images data path.</value>
|
||||
public string VideoImagesPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(ConfigurationManager.ApplicationPaths.DataPath, "extracted-video-images");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the audio image path.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private string GetVideoImagePath(Video item)
|
||||
{
|
||||
var filename = item.Path + "_" + item.DateModified.Ticks + "_primary";
|
||||
|
||||
filename = filename.GetMD5() + ".jpg";
|
||||
|
||||
var prefix = filename.Substring(0, 1);
|
||||
|
||||
return Path.Combine(VideoImagesPath, prefix, filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -898,6 +898,15 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queues the library scan.
|
||||
/// </summary>
|
||||
public void QueueLibraryScan()
|
||||
{
|
||||
// Just run the scheduled task so that the user can see it
|
||||
_taskManager.QueueScheduledTask<RefreshMediaLibraryTask>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the media library internal.
|
||||
/// </summary>
|
||||
|
|
|
@ -420,14 +420,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
{
|
||||
var info = _tvDtoService.GetTimerInfo(timer);
|
||||
|
||||
return ActiveService.UpdateTimerAsync(info, cancellationToken);
|
||||
var service = GetServices(timer.ServiceName, null)
|
||||
.First();
|
||||
|
||||
return service.UpdateTimerAsync(info, cancellationToken);
|
||||
}
|
||||
|
||||
public Task UpdateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken)
|
||||
{
|
||||
var info = _tvDtoService.GetSeriesTimerInfo(timer);
|
||||
|
||||
return ActiveService.UpdateSeriesTimerAsync(info, cancellationToken);
|
||||
var service = GetServices(timer.ServiceName, null)
|
||||
.First();
|
||||
|
||||
return service.UpdateSeriesTimerAsync(info, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<QueryResult<SeriesTimerInfoDto>> GetSeriesTimers(SeriesTimerQuery query, CancellationToken cancellationToken)
|
||||
|
|
|
@ -145,7 +145,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
|
|||
|
||||
var numComplete = 0;
|
||||
|
||||
var failHistoryPath = Path.Combine(_kernel.FFMpegManager.VideoImagesDataPath, "failures.txt");
|
||||
var failHistoryPath = Path.Combine(_kernel.FFMpegManager.ChapterImagesPath, "failures.txt");
|
||||
|
||||
List<string> previouslyFailedImages;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user