Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract all subtitle streams simultaneously #10884

Merged
merged 2 commits into from
Feb 3, 2024

Conversation

alltilla
Copy link
Contributor

Changes

Extracting a subtitle stream is a disk I/O bottlenecked operation as ffmpeg has to read through the whole file, but usually there is nothing CPU intensive to do.

If a file has multiple subtitle streams, and we want to extract more of them, extracting them one-by-one results in reading the whole file again and again.

However ffmpeg can extract multiple streams at once.

We can optimize this by extracting the subtitle streams all at once when only one of them gets queried, then we will have all of them cached for later use.

It is useful for people switching subtitles during playback.

It is even more useful for people who extract all the subtitle streams in advance, for example with the "Subtitle Extract" plugin.
In this case we reduce the extraction time significantly based on the number of subtitle streams in the files, which can be 5-10 in many cases.


Jellyfin logs

[2024-01-18 16:20:21.903 +00:00] [INF] [22] MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder: "/usr/lib/jellyfin-ffmpeg/ffmpeg" "-i /data/fulcrum-smmatsv.2023.2160p.dvhdr.mkv -copyts -map 0:3 -an -vn -c:s copy \"/config/data/subtitles/e/e03bae81-b63d-9ef4-a9f1-565757dfa367.srt\" -map 0:4 -an -vn -c:s copy \"/config/data/subtitles/2/2aa4f2fd-3a67-1f5a-8f58-b76ab90995ba.srt\" -map 0:5 -an -vn -c:s copy \"/config/data/subtitles/7/772afa8b-fcb5-9fc0-c155-586d36289218.srt\" -map 0:6 -an -vn -c:s copy \"/config/data/subtitles/2/2632fefa-5488-1c79-7684-0e1306e0bcfd.srt\""
[2024-01-18 16:21:11.389 +00:00] [INF] [11] MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder: ffmpeg subtitle extraction completed for "/data/fulcrum-smmatsv.2023.2160p.dvhdr.mkv" to "/config/data/subtitles/e/e03bae81-b63d-9ef4-a9f1-565757dfa367.srt"
[2024-01-18 16:21:11.390 +00:00] [INF] [11] MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder: ffmpeg subtitle extraction completed for "/data/fulcrum-smmatsv.2023.2160p.dvhdr.mkv" to "/config/data/subtitles/2/2aa4f2fd-3a67-1f5a-8f58-b76ab90995ba.srt"
[2024-01-18 16:21:11.390 +00:00] [INF] [11] MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder: ffmpeg subtitle extraction completed for "/data/fulcrum-smmatsv.2023.2160p.dvhdr.mkv" to "/config/data/subtitles/7/772afa8b-fcb5-9fc0-c155-586d36289218.srt"
[2024-01-18 16:21:11.390 +00:00] [INF] [11] MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder: ffmpeg subtitle extraction completed for "/data/fulcrum-smmatsv.2023.2160p.dvhdr.mkv" to "/config/data/subtitles/2/2632fefa-5488-1c79-7684-0e1306e0bcfd.srt"

ffmpeg logs

ffmpeg version 6.0.1-Jellyfin Copyright (c) 2000-2023 the FFmpeg developers
  built with gcc 12 (Debian 12.2.0-14)
  configuration: --prefix=/usr/lib/jellyfin-ffmpeg --target-os=linux --extra-version=Jellyfin --disable-doc --disable-ffplay --disable-ptx-compression --disable-static --disable-libxcb --disa
ble-sdl2 --disable-xlib --enable-lto --enable-gpl --enable-version3 --enable-shared --enable-gmp --enable-gnutls --enable-chromaprint --enable-libdrm --enable-libass --enable-libfreetype --en
able-libfribidi --enable-libfontconfig --enable-libbluray --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libopenmpt --enable-libdav1d --enable-libwebp --e
nable-libvpx --enable-libx264 --enable-libx265 --enable-libzvbi --enable-libzimg --enable-libfdk-aac --arch=amd64 --enable-libsvtav1 --enable-libshaderc --enable-libplacebo --enable-vulkan --
enable-opencl --enable-vaapi --enable-amf --enable-libvpl --enable-ffnvcodec --enable-cuda --enable-cuda-llvm --enable-cuvid --enable-nvdec --enable-nvenc
  libavutil      58.  2.100 / 58.  2.100
  libavcodec     60.  3.100 / 60.  3.100
  libavformat    60.  3.100 / 60.  3.100
  libavdevice    60.  1.100 / 60.  1.100
  libavfilter     9.  3.100 /  9.  3.100
  libswscale      7.  1.100 /  7.  1.100
  libswresample   4. 10.100 /  4. 10.100
  libpostproc    57.  1.100 / 57.  1.100
Input #0, matroska,webm, from '/data/fulcrum-smmatsv.2023.2160p.dvhdr.mkv':
  Metadata:
    title           : Spider-Man.Across.the.Spider-Verse.2023.READ.NFO.2160p.MA.WEB-DL.DV.HDR.DDP5.1.Atmos.H.265.HUN-FULCRUM
    encoder         : libebml v1.4.3 + libmatroska v1.7.0
    creation_time   : 2023-08-08T14:43:38.000000Z
  Duration: 02:20:05.79, start: 0.000000, bitrate: 25725 kb/s
  Chapters:
    Chapter #0:0: start 0.000000, end 543.000000
      Metadata:
        title           : Chapter 01
    Chapter #0:1: start 543.000000, end 1198.000000
      Metadata:
        title           : Chapter 02
    Chapter #0:2: start 1198.000000, end 1619.000000
      Metadata:
        title           : Chapter 03
    Chapter #0:3: start 1619.000000, end 2207.000000
      Metadata:
        title           : Chapter 04
    Chapter #0:4: start 2207.000000, end 2686.000000
      Metadata:
        title           : Chapter 05
    Chapter #0:5: start 2686.000000, end 3151.000000
      Metadata:
        title           : Chapter 06
    Chapter #0:6: start 3151.000000, end 3845.000000
      Metadata:
        title           : Chapter 07
    Chapter #0:7: start 3845.000000, end 4315.000000
      Metadata:
        title           : Chapter 08
    Chapter #0:8: start 4315.000000, end 4901.000000
      Metadata:
        title           : Chapter 09
    Chapter #0:9: start 4901.000000, end 5450.000000
      Metadata:
        title           : Chapter 10
    Chapter #0:10: start 5450.000000, end 6005.000000
      Metadata:
        title           : Chapter 11
    Chapter #0:11: start 6005.000000, end 6476.000000
      Metadata:
        title           : Chapter 12
    Chapter #0:12: start 6476.000000, end 7109.000000
      Metadata:
        title           : Chapter 13
    Chapter #0:13: start 7109.000000, end 7520.000000
      Metadata:
        title           : Chapter 14
    Chapter #0:14: start 7520.000000, end 8008.000000
      Metadata:
        title           : Chapter 15
    Chapter #0:15: start 8008.000000, end 8405.792000
      Metadata:
        title           : Chapter 16
  Stream #0:0(hun): Video: hevc (Main 10), yuv420p10le(tv, bt2020nc/bt2020/smpte2084), 3840x2160 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn (default)
    Metadata:
      title           : In FULCRUM we trust
      BPS             : 24314995
      DURATION        : 02:20:05.731000000
      NUMBER_OF_FRAMES: 201536
      NUMBER_OF_BYTES : 25548163467
      _STATISTICS_WRITING_APP: mkvmerge v70.0.0.32 ('Caught A Lite Sneeze') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2023-08-08 14:43:38
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
    Side data:
      DOVI configuration record: version: 1.0, profile: 8, level: 6, rpu flag: 1, el flag: 0, bl flag: 1, compatibility id: 1
  Stream #0:1(hun): Audio: eac3, 48000 Hz, 5.1(side), fltp, 640 kb/s (default)
    Metadata:
      title           : DDP 5.1
      BPS             : 640000
      DURATION        : 02:20:05.760000000
      NUMBER_OF_FRAMES: 262680
      NUMBER_OF_BYTES : 672460800
      _STATISTICS_WRITING_APP: mkvmerge v70.0.0.32 ('Caught A Lite Sneeze') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2023-08-08 14:43:38
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
  Stream #0:2(eng): Audio: eac3, 48000 Hz, 5.1(side), fltp, 768 kb/s
    Metadata:
      title           : DDP 5.1
      BPS             : 768000
      DURATION        : 02:20:05.792000000
      NUMBER_OF_FRAMES: 262681
      NUMBER_OF_BYTES : 806956032
      _STATISTICS_WRITING_APP: mkvmerge v70.0.0.32 ('Caught A Lite Sneeze') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2023-08-08 14:43:38
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
  Stream #0:3(hun): Subtitle: subrip (default) (forced)
    Metadata:
      title           : Forced
      BPS             : 0
      DURATION        : 02:19:54.853000000
      NUMBER_OF_FRAMES: 18
      NUMBER_OF_BYTES : 408
      _STATISTICS_WRITING_APP: mkvmerge v70.0.0.32 ('Caught A Lite Sneeze') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2023-08-08 14:43:38
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
  Stream #0:4(hun): Subtitle: subrip
    Metadata:
      title           : Full
      BPS             : 55
      DURATION        : 02:19:54.853000000
      NUMBER_OF_FRAMES: 2021
      NUMBER_OF_BYTES : 58266
      _STATISTICS_WRITING_APP: mkvmerge v70.0.0.32 ('Caught A Lite Sneeze') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2023-08-08 14:43:38
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
  Stream #0:5(eng): Subtitle: subrip (original)
    Metadata:
      title           : Full
      BPS             : 69
      DURATION        : 02:11:59.912000000
      NUMBER_OF_FRAMES: 1993
      NUMBER_OF_BYTES : 68440
      _STATISTICS_WRITING_APP: mkvmerge v70.0.0.32 ('Caught A Lite Sneeze') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2023-08-08 14:43:38
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
  Stream #0:6(eng): Subtitle: subrip (original) (hearing impaired)
    Metadata:
      title           : SDH
      BPS             : 76
      DURATION        : 02:16:52.787000000
      NUMBER_OF_FRAMES: 2241
      NUMBER_OF_BYTES : 78323
      _STATISTICS_WRITING_APP: mkvmerge v70.0.0.32 ('Caught A Lite Sneeze') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2023-08-08 14:43:38
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Output #0, srt, to '/config/data/subtitles/e/e03bae81-b63d-9ef4-a9f1-565757dfa367.srt':
  Metadata:
    title           : Spider-Man.Across.the.Spider-Verse.2023.READ.NFO.2160p.MA.WEB-DL.DV.HDR.DDP5.1.Atmos.H.265.HUN-FULCRUM
    encoder         : Lavf60.3.100
  Chapters:
    Chapter #0:0: start 0.000000, end 543.000000
      Metadata:
        title           : Chapter 01
    Chapter #0:1: start 543.000000, end 1198.000000
      Metadata:
        title           : Chapter 02
    Chapter #0:2: start 1198.000000, end 1619.000000
      Metadata:
        title           : Chapter 03
    Chapter #0:3: start 1619.000000, end 2207.000000
      Metadata:
        title           : Chapter 04
    Chapter #0:4: start 2207.000000, end 2686.000000
      Metadata:
        title           : Chapter 05
    Chapter #0:5: start 2686.000000, end 3151.000000
      Metadata:
        title           : Chapter 06
    Chapter #0:6: start 3151.000000, end 3845.000000
      Metadata:
        title           : Chapter 07
    Chapter #0:7: start 3845.000000, end 4315.000000
      Metadata:
        title           : Chapter 08
    Chapter #0:8: start 4315.000000, end 4901.000000
      Metadata:
        title           : Chapter 09
    Chapter #0:9: start 4901.000000, end 5450.000000
      Metadata:
        title           : Chapter 10
    Chapter #0:10: start 5450.000000, end 6005.000000
      Metadata:
        title           : Chapter 11
    Chapter #0:11: start 6005.000000, end 6476.000000
      Metadata:
        title           : Chapter 12
    Chapter #0:12: start 6476.000000, end 7109.000000
      Metadata:
        title           : Chapter 13
    Chapter #0:13: start 7109.000000, end 7520.000000
      Metadata:
        title           : Chapter 14
    Chapter #0:14: start 7520.000000, end 8008.000000
      Metadata:
        title           : Chapter 15
    Chapter #0:15: start 8008.000000, end 8405.792000
      Metadata:
        title           : Chapter 16
  Stream #0:0(hun): Subtitle: subrip (default) (forced)
    Metadata:
      title           : Forced
      BPS             : 0
      DURATION        : 02:19:54.853000000
      NUMBER_OF_FRAMES: 18
      NUMBER_OF_BYTES : 408
      _STATISTICS_WRITING_APP: mkvmerge v70.0.0.32 ('Caught A Lite Sneeze') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2023-08-08 14:43:38
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Output #1, srt, to '/config/data/subtitles/2/2aa4f2fd-3a67-1f5a-8f58-b76ab90995ba.srt':
  Metadata:
    title           : Spider-Man.Across.the.Spider-Verse.2023.READ.NFO.2160p.MA.WEB-DL.DV.HDR.DDP5.1.Atmos.H.265.HUN-FULCRUM
    encoder         : Lavf60.3.100
  Chapters:
    Chapter #1:0: start 0.000000, end 543.000000
      Metadata:
        title           : Chapter 01
    Chapter #1:1: start 543.000000, end 1198.000000
      Metadata:
        title           : Chapter 02
    Chapter #1:2: start 1198.000000, end 1619.000000
      Metadata:
        title           : Chapter 03
    Chapter #1:3: start 1619.000000, end 2207.000000
      Metadata:
        title           : Chapter 04
    Chapter #1:4: start 2207.000000, end 2686.000000
      Metadata:
        title           : Chapter 05
    Chapter #1:5: start 2686.000000, end 3151.000000
      Metadata:
        title           : Chapter 06
    Chapter #1:6: start 3151.000000, end 3845.000000
      Metadata:
        title           : Chapter 07
    Chapter #1:7: start 3845.000000, end 4315.000000
      Metadata:
        title           : Chapter 08
    Chapter #1:8: start 4315.000000, end 4901.000000
      Metadata:
        title           : Chapter 09
    Chapter #1:9: start 4901.000000, end 5450.000000
      Metadata:
        title           : Chapter 10
    Chapter #1:10: start 5450.000000, end 6005.000000
      Metadata:
        title           : Chapter 11
    Chapter #1:11: start 6005.000000, end 6476.000000
      Metadata:
        title           : Chapter 12
    Chapter #1:12: start 6476.000000, end 7109.000000
      Metadata:
        title           : Chapter 13
    Chapter #1:13: start 7109.000000, end 7520.000000
      Metadata:
        title           : Chapter 14
    Chapter #1:14: start 7520.000000, end 8008.000000
      Metadata:
        title           : Chapter 15
    Chapter #1:15: start 8008.000000, end 8405.792000
      Metadata:
        title           : Chapter 16
  Stream #1:0(hun): Subtitle: subrip
    Metadata:
      title           : Full
      BPS             : 55
      DURATION        : 02:19:54.853000000
      NUMBER_OF_FRAMES: 2021
      NUMBER_OF_BYTES : 58266
      _STATISTICS_WRITING_APP: mkvmerge v70.0.0.32 ('Caught A Lite Sneeze') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2023-08-08 14:43:38
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Output #2, srt, to '/config/data/subtitles/7/772afa8b-fcb5-9fc0-c155-586d36289218.srt':
  Metadata:
    title           : Spider-Man.Across.the.Spider-Verse.2023.READ.NFO.2160p.MA.WEB-DL.DV.HDR.DDP5.1.Atmos.H.265.HUN-FULCRUM
    encoder         : Lavf60.3.100
  Chapters:
    Chapter #2:0: start 0.000000, end 543.000000
      Metadata:
        title           : Chapter 01
    Chapter #2:1: start 543.000000, end 1198.000000
      Metadata:
        title           : Chapter 02
    Chapter #2:2: start 1198.000000, end 1619.000000
      Metadata:
        title           : Chapter 03
    Chapter #2:3: start 1619.000000, end 2207.000000
      Metadata:
        title           : Chapter 04
    Chapter #2:4: start 2207.000000, end 2686.000000
      Metadata:
        title           : Chapter 05
    Chapter #2:5: start 2686.000000, end 3151.000000
      Metadata:
        title           : Chapter 06
    Chapter #2:6: start 3151.000000, end 3845.000000
      Metadata:
        title           : Chapter 07
    Chapter #2:7: start 3845.000000, end 4315.000000
      Metadata:
        title           : Chapter 08
    Chapter #2:8: start 4315.000000, end 4901.000000
      Metadata:
        title           : Chapter 09
    Chapter #2:9: start 4901.000000, end 5450.000000
      Metadata:
        title           : Chapter 10
    Chapter #2:10: start 5450.000000, end 6005.000000
      Metadata:
        title           : Chapter 11
    Chapter #2:11: start 6005.000000, end 6476.000000
      Metadata:
        title           : Chapter 12
    Chapter #2:12: start 6476.000000, end 7109.000000
      Metadata:
        title           : Chapter 13
    Chapter #2:13: start 7109.000000, end 7520.000000
      Metadata:
        title           : Chapter 14
    Chapter #2:14: start 7520.000000, end 8008.000000
      Metadata:
        title           : Chapter 15
    Chapter #2:15: start 8008.000000, end 8405.792000
      Metadata:
        title           : Chapter 16
  Stream #2:0(eng): Subtitle: subrip (original)
    Metadata:
      title           : Full
      BPS             : 69
      DURATION        : 02:11:59.912000000
      NUMBER_OF_FRAMES: 1993
      NUMBER_OF_BYTES : 68440
      _STATISTICS_WRITING_APP: mkvmerge v70.0.0.32 ('Caught A Lite Sneeze') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2023-08-08 14:43:38
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Output #3, srt, to '/config/data/subtitles/2/2632fefa-5488-1c79-7684-0e1306e0bcfd.srt':
  Metadata:
    title           : Spider-Man.Across.the.Spider-Verse.2023.READ.NFO.2160p.MA.WEB-DL.DV.HDR.DDP5.1.Atmos.H.265.HUN-FULCRUM
    encoder         : Lavf60.3.100
  Chapters:
    Chapter #3:0: start 0.000000, end 543.000000
      Metadata:
        title           : Chapter 01
    Chapter #3:1: start 543.000000, end 1198.000000
      Metadata:
        title           : Chapter 02
    Chapter #3:2: start 1198.000000, end 1619.000000
      Metadata:
        title           : Chapter 03
    Chapter #3:3: start 1619.000000, end 2207.000000
      Metadata:
        title           : Chapter 04
    Chapter #3:4: start 2207.000000, end 2686.000000
      Metadata:
        title           : Chapter 05
    Chapter #3:5: start 2686.000000, end 3151.000000
      Metadata:
        title           : Chapter 06
    Chapter #3:6: start 3151.000000, end 3845.000000
      Metadata:
        title           : Chapter 07
    Chapter #3:7: start 3845.000000, end 4315.000000
      Metadata:
        title           : Chapter 08
    Chapter #3:8: start 4315.000000, end 4901.000000
      Metadata:
        title           : Chapter 09
    Chapter #3:9: start 4901.000000, end 5450.000000
      Metadata:
        title           : Chapter 10
    Chapter #3:10: start 5450.000000, end 6005.000000
      Metadata:
        title           : Chapter 11
    Chapter #3:11: start 6005.000000, end 6476.000000
      Metadata:
        title           : Chapter 12
    Chapter #3:12: start 6476.000000, end 7109.000000
      Metadata:
        title           : Chapter 13
    Chapter #3:13: start 7109.000000, end 7520.000000
      Metadata:
        title           : Chapter 14
    Chapter #3:14: start 7520.000000, end 8008.000000
      Metadata:
        title           : Chapter 15
    Chapter #3:15: start 8008.000000, end 8405.792000
      Metadata:
        title           : Chapter 16
  Stream #3:0(eng): Subtitle: subrip (original) (hearing impaired)
    Metadata:
      title           : SDH
      BPS             : 76
      DURATION        : 02:16:52.787000000
      NUMBER_OF_FRAMES: 2241
      NUMBER_OF_BYTES : 78323
      _STATISTICS_WRITING_APP: mkvmerge v70.0.0.32 ('Caught A Lite Sneeze') 64-bit
      _STATISTICS_WRITING_DATE_UTC: 2023-08-08 14:43:38
      _STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream mapping:
  Stream #0:3 -> #0:0 (copy)
  Stream #0:4 -> #1:0 (copy)
  Stream #0:5 -> #2:0 (copy)
  Stream #0:6 -> #3:0 (copy)
Press [q] to stop, [?] for help
size=       1kB time=02:19:34.41 bitrate=   0.0kbits/s speed= 170x
video:0kB audio:0kB subtitle:201kB other streams:0kB global headers:0kB muxing overhead: unknown

Extracting a subtitle stream is a disk I/O bottlenecked operation as
ffmpeg has to read through the whole file, but usually there is nothing
CPU intensive to do.

If a file has multiple subtitle streams, and we want to extract more
of them, extracting them one-by-one results in reading the whole file
again and again.

However ffmpeg can extract multiple streams at once.

We can optimize this by extracting the subtitle streams all at once
when only one of them gets queried, then we will have all of them
cached for later use.

It is useful for people switching subtitles during playback.

It is even more useful for people who extract all the subtitle streams
in advance, for example with the "Subtitle Extract" plugin.
In this case we reduce the extraction time significantly based on the
number of subtitle streams in the files, which can be 5-10 in many
cases.

Signed-off-by: Attila Szakacs <szakacs.attila96@gmail.com>
@mirolm
Copy link

mirolm commented Jan 30, 2024

Jellyfin have a tendency to choke the storage when there are tons of attachments. Usially this happens with anime shows. I opened an old issue about this that can be used as a reference.

If this fixes the above issue alot people with slower storage and low memory hardware will be happy.

Copy link
Member

@barronpm barronpm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor formatting notes, cc @nyanmisaka for the substance of the changes

MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs Outdated Show resolved Hide resolved
MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs Outdated Show resolved Hide resolved
MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs Outdated Show resolved Hide resolved
MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs Outdated Show resolved Hide resolved
@alltilla alltilla force-pushed the extract-all-subtitles branch from cd1f290 to 005c215 Compare January 31, 2024 18:04
@alltilla
Copy link
Contributor Author

Thank you for the review!

I have fixed all your comments, here's the diff:

diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index 0e66565ed..3230927a6 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -472,8 +472,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles
         /// <returns>Task.</returns>
         private async Task ExtractAllTextSubtitles(MediaSourceInfo mediaSource, CancellationToken cancellationToken)
         {
-            var semaphores = new List<SemaphoreSlim> { };
-            var extractableStreams = new List<MediaStream> { };
+            var semaphores = new List<SemaphoreSlim>();
+            var extractableStreams = new List<MediaStream>();
 
             try
             {
@@ -498,9 +498,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                 }
 
                 if (extractableStreams.Count > 0)
-                    {
-                        await ExtractAllTextSubtitlesInternal(mediaSource, extractableStreams, cancellationToken).ConfigureAwait(false);
-                    }
+                {
+                    await ExtractAllTextSubtitlesInternal(mediaSource, extractableStreams, cancellationToken).ConfigureAwait(false);
+                }
             }
             catch (Exception ex)
             {
@@ -521,7 +521,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
             CancellationToken cancellationToken)
         {
             var inputPath = mediaSource.Path;
-            var outputPaths = new List<string> { };
+            var outputPaths = new List<string>();
             var args = string.Format(
                 CultureInfo.InvariantCulture,
                 "-i {0} -copyts",
@@ -531,6 +531,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles
             {
                 var outputPath = GetSubtitleCachePath(mediaSource, subtitleStream.Index, "." + GetTextSubtitleFormat(subtitleStream));
                 var outputCodec = IsCodecCopyable(subtitleStream.Codec) ? "copy" : "srt";
+                var streamIndex = EncodingHelper.FindIndex(mediaSource.MediaStreams, subtitleStream);
+
+                if (streamIndex == -1)
+                {
+                    _logger.LogError("Cannot find subtitle stream index for {InputPath} ({Index}), skipping this stream", inputPath, subtitleStream.Index);
+                    continue;
+                }
 
                 Directory.CreateDirectory(Path.GetDirectoryName(outputPath) ?? throw new FileNotFoundException($"Calculated path ({outputPath}) is not valid."));
 
@@ -538,7 +545,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                 args += string.Format(
                     CultureInfo.InvariantCulture,
                     " -map 0:{0} -an -vn -c:s {1} \"{2}\"",
-                    subtitleStream.Index,
+                    streamIndex,
                     outputCodec,
                     outputPath);
             }
@@ -614,18 +621,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                     {
                         _logger.LogError("ffmpeg subtitle extraction failed for {InputPath} to {OutputPath}", inputPath, outputPath);
                         failed = true;
+                        continue;
                     }
-                    else
+                    if (outputPath.EndsWith("ass", StringComparison.OrdinalIgnoreCase))
                     {
-                        if (outputPath.EndsWith("ass", StringComparison.OrdinalIgnoreCase))
-                        {
-                            await SetAssFont(outputPath, cancellationToken).ConfigureAwait(false);
-                        }
-
-                        _logger.LogInformation("ffmpeg subtitle extraction completed for {InputPath} to {OutputPath}", inputPath, outputPath);
+                        await SetAssFont(outputPath, cancellationToken).ConfigureAwait(false);
+                    }
+                    _logger.LogInformation("ffmpeg subtitle extraction completed for {InputPath} to {OutputPath}", inputPath, outputPath);
                     }
                 }
-            }
 
             if (failed)
             {

Signed-off-by: Attila Szakacs <szakacs.attila96@gmail.com>
@alltilla alltilla force-pushed the extract-all-subtitles branch from 005c215 to ce81e2a Compare January 31, 2024 18:19
@alltilla
Copy link
Contributor Author

alltilla commented Jan 31, 2024

🤦 Sorry, thanks!

@nyanmisaka nyanmisaka added the enhancement Improving an existing function, or small fixes label Feb 1, 2024
@crobibero crobibero merged commit 81cf4b6 into jellyfin:master Feb 3, 2024
25 checks passed
KrzaQ pushed a commit to KrzaQ/jellyfin that referenced this pull request Feb 13, 2024
Extract all subtitle streams simultaneously
alltilla added a commit to alltilla/jellyfin that referenced this pull request Feb 18, 2024
Similar to jellyfin#10884

---

Extracting a media attachment is a disk I/O bottlenecked operation as
ffmpeg has to read through the whole file, but usually there is nothing
CPU intensive to do.

If a file has multiple media attachments, and we want to extract more of
them, extracting them one-by-one results in reading the whole file again
and again.

However ffmpeg can extract multiple streams at once.

We can optimize this by extracting the media attachments all at once
when only one of them gets queried, then we will have all of them cached
for later use.

---

Jellyfin clients need fonts for subtitles, and each font is a separate
attachment, which causes a lot of re-reads of the file. Certain contents,
like anime in a lot of cases, contain 10-50 different attachments;
reading the same 2-3 GB file 50 times from a HDD takes a significant
amount of time.

This change helps a lot in this scenario.

Signed-off-by: Attila Szakacs <szakacs.attila96@gmail.com>
alltilla added a commit to alltilla/jellyfin that referenced this pull request Feb 18, 2024
Similar to jellyfin#10884

---

Jellyfin clients need fonts for subtitles, and each font is a separate
attachment, which causes a lot of re-reads of the file. Certain contents,
like anime in a lot of cases, contain 50-80 different attachments.

Spawning 80 ffmpeg processes at the same time on the same file might
cause swapping on slower HDDs and can bring disk subsystem to a crawl.

(For more info, see https://github.com/jellyfin/jellyfin/3215)

This change helps a lot in this scenario.

Signed-off-by: Attila Szakacs <szakacs.attila96@gmail.com>
@fa1rid
Copy link

fa1rid commented Feb 21, 2024

I was thinking if there is a way to stream subtitles directly from the video file without extraction, or perhaps extracting the subtitle without the need to read the whole file. Do video players like VLC, etc, read the whole file to play subtitles?

@nyanmisaka
Copy link
Member

For non-SSA/ASS plain text subtitles, it is possible to pass the subtitles to the HLS player via HLS/m3u8. This requires additional efforts in both server and clients.

alltilla added a commit to alltilla/jellyfin that referenced this pull request Feb 24, 2024
Similar to jellyfin#10884

---

Jellyfin clients need fonts for subtitles, and each font is a separate
attachment, which causes a lot of re-reads of the file. Certain contents,
like anime in a lot of cases, contain 50-80 different attachments.

Spawning 80 ffmpeg processes at the same time on the same file might
cause swapping on slower HDDs and can bring disk subsystem to a crawl.

(For more info, see https://github.com/jellyfin/jellyfin/3215)

This change helps a lot in this scenario.

Signed-off-by: Attila Szakacs <szakacs.attila96@gmail.com>
crobibero pushed a commit that referenced this pull request Mar 3, 2024
Similar to #10884

---

Jellyfin clients need fonts for subtitles, and each font is a separate
attachment, which causes a lot of re-reads of the file. Certain contents,
like anime in a lot of cases, contain 50-80 different attachments.

Spawning 80 ffmpeg processes at the same time on the same file might
cause swapping on slower HDDs and can bring disk subsystem to a crawl.

(For more info, see https://github.com/jellyfin/jellyfin/3215)

This change helps a lot in this scenario.

Signed-off-by: Attila Szakacs <szakacs.attila96@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improving an existing function, or small fixes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants