2
0

FixAudioData.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. using System;
  2. using System.Globalization;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Threading;
  6. using Jellyfin.Data.Enums;
  7. using MediaBrowser.Controller;
  8. using MediaBrowser.Controller.Entities;
  9. using MediaBrowser.Controller.Entities.Audio;
  10. using MediaBrowser.Controller.Persistence;
  11. using MediaBrowser.Model.Entities;
  12. using Microsoft.Extensions.Logging;
  13. namespace Jellyfin.Server.Migrations.Routines
  14. {
  15. /// <summary>
  16. /// Fixes the data column of audio types to be deserializable.
  17. /// </summary>
  18. internal class FixAudioData : IMigrationRoutine
  19. {
  20. private const string DbFilename = "library.db";
  21. private readonly ILogger<FixAudioData> _logger;
  22. private readonly IServerApplicationPaths _applicationPaths;
  23. private readonly IItemRepository _itemRepository;
  24. public FixAudioData(
  25. IServerApplicationPaths applicationPaths,
  26. ILoggerFactory loggerFactory,
  27. IItemRepository itemRepository)
  28. {
  29. _applicationPaths = applicationPaths;
  30. _itemRepository = itemRepository;
  31. _logger = loggerFactory.CreateLogger<FixAudioData>();
  32. }
  33. /// <inheritdoc/>
  34. public Guid Id => Guid.Parse("{CF6FABC2-9FBE-4933-84A5-FFE52EF22A58}");
  35. /// <inheritdoc/>
  36. public string Name => "FixAudioData";
  37. /// <inheritdoc/>
  38. public bool PerformOnNewInstall => false;
  39. /// <inheritdoc/>
  40. public void Perform()
  41. {
  42. var dbPath = Path.Combine(_applicationPaths.DataPath, DbFilename);
  43. // Back up the database before modifying any entries
  44. for (int i = 1; ; i++)
  45. {
  46. var bakPath = string.Format(CultureInfo.InvariantCulture, "{0}.bak{1}", dbPath, i);
  47. if (!File.Exists(bakPath))
  48. {
  49. try
  50. {
  51. File.Copy(dbPath, bakPath);
  52. _logger.LogInformation("Library database backed up to {BackupPath}", bakPath);
  53. break;
  54. }
  55. catch (Exception ex)
  56. {
  57. _logger.LogError(ex, "Cannot make a backup of {Library} at path {BackupPath}", DbFilename, bakPath);
  58. throw;
  59. }
  60. }
  61. }
  62. _logger.LogInformation("Backfilling audio lyrics data to database.");
  63. var startIndex = 0;
  64. var records = _itemRepository.GetCount(new InternalItemsQuery
  65. {
  66. IncludeItemTypes = [BaseItemKind.Audio],
  67. });
  68. while (startIndex < records)
  69. {
  70. var results = _itemRepository.GetItemList(new InternalItemsQuery
  71. {
  72. IncludeItemTypes = [BaseItemKind.Audio],
  73. StartIndex = startIndex,
  74. Limit = 100,
  75. SkipDeserialization = true
  76. })
  77. .Cast<Audio>()
  78. .ToList();
  79. foreach (var audio in results)
  80. {
  81. var lyricMediaStreams = audio.GetMediaStreams().Where(s => s.Type == MediaStreamType.Lyric).Select(s => s.Path).ToList();
  82. if (lyricMediaStreams.Count > 0)
  83. {
  84. audio.HasLyrics = true;
  85. audio.LyricFiles = lyricMediaStreams;
  86. }
  87. }
  88. _itemRepository.SaveItems(results, CancellationToken.None);
  89. startIndex += 100;
  90. }
  91. }
  92. }
  93. }