FixAudioData.cs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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. #pragma warning disable CS0618 // Type or member is obsolete
  19. [JellyfinMigration("2025-04-20T18:00:00", nameof(FixAudioData), "CF6FABC2-9FBE-4933-84A5-FFE52EF22A58")]
  20. [JellyfinMigrationBackup(LegacyLibraryDb = true)]
  21. internal class FixAudioData : IMigrationRoutine
  22. #pragma warning restore CS0618 // Type or member is obsolete
  23. {
  24. private readonly ILogger<FixAudioData> _logger;
  25. private readonly IServerApplicationPaths _applicationPaths;
  26. private readonly IItemRepository _itemRepository;
  27. public FixAudioData(
  28. IServerApplicationPaths applicationPaths,
  29. ILoggerFactory loggerFactory,
  30. IItemRepository itemRepository)
  31. {
  32. _applicationPaths = applicationPaths;
  33. _itemRepository = itemRepository;
  34. _logger = loggerFactory.CreateLogger<FixAudioData>();
  35. }
  36. /// <inheritdoc/>
  37. public void Perform()
  38. {
  39. _logger.LogInformation("Backfilling audio lyrics data to database.");
  40. var startIndex = 0;
  41. var records = _itemRepository.GetCount(new InternalItemsQuery
  42. {
  43. IncludeItemTypes = [BaseItemKind.Audio],
  44. });
  45. while (startIndex < records)
  46. {
  47. var results = _itemRepository.GetItemList(new InternalItemsQuery
  48. {
  49. IncludeItemTypes = [BaseItemKind.Audio],
  50. StartIndex = startIndex,
  51. Limit = 5000,
  52. SkipDeserialization = true
  53. })
  54. .Cast<Audio>()
  55. .ToList();
  56. foreach (var audio in results)
  57. {
  58. var lyricMediaStreams = audio.GetMediaStreams().Where(s => s.Type == MediaStreamType.Lyric).Select(s => s.Path).ToList();
  59. if (lyricMediaStreams.Count > 0)
  60. {
  61. audio.HasLyrics = true;
  62. audio.LyricFiles = lyricMediaStreams;
  63. }
  64. }
  65. _itemRepository.SaveItems(results, CancellationToken.None);
  66. startIndex += results.Count;
  67. _logger.LogInformation("Backfilled data for {UpdatedRecords} of {TotalRecords} audio records", startIndex, records);
  68. }
  69. }
  70. }
  71. }