On the Causes and Consequences of Jellyfin's Caption Rendering Errors and Solutions
Antecedent knowledge
The habitual name only represents the personal opinion within the scope of Zimiao's haunting blog (azimiao. com).
-
Hard Caption
When pressing, the caption image is directly rendered on the video image. -
Internal subtitles/internal subtitles/internal subtitles
Encapsulate one or more subtitle streams in MKV and other packages, and render subtitles according to the specified timeline and style information during decoding. -
External subtitles
It is similar to the built-in subtitle, but the subtitle is a separate subtitle file that is not encapsulated in the video file.
Caption rendering of Jellyfin
Only Jellyfin Server+Jellyfin Web will be discussed. Generally, third-party clients based on WebView are similar.
Two rendering modes
-
Burn subtitle image -
Front end rendering caption
Timing
Error rendering subtitles in burning subtitle image mode
Note that the configuration is for libass: FFmpeg does not come with any fonts FFmpeg uses libass to burn subtitles, which in turn uses fontconfig to scan fonts available on system and use them.
//Jellyfin EncodingHelper.cs var fontPath = Path.Combine(_appPaths. CachePath, "attachments", state.MediaSource.Id); var fontParam = string.Format( CultureInfo.InvariantCulture, ":fontsdir='{0}'", _mediaEncoder. EscapeSubtitleFilterPath(fontPath));
Error rendering subtitles in front-end rendering mode
-
Get font list -
Get subtitle file -
Parsing subtitle files (timeline, FontStyle, FontText, etc.) -
Rendering subtitles based on video timeline and FontStyle
1. Video with embedded font
# Get /Videos/[VideoUID]/[VideoUID]/Attachments/*
2. Video without embedded font
-
Sorted according to the priority of small file size/top name/latest modification time/latest creation time; -
Take the first few in the sorting list. When the total font size in the list is greater than 20M, no new font will be added.
//Zimiao.com fork from github/jellyfin/jellyfin public IEnumerable<FontFile> GetFallbackFontList() { var encodingOptions = _serverConfigurationManager.GetEncodingOptions(); var fallbackFontPath = encodingOptions.FallbackFontPath; if (! string.IsNullOrEmpty(fallbackFontPath)) { var files = _fileSystem.GetFiles(fallbackFontPath, new[] { ".woff", ".woff2", ".ttf", ".otf" }, false, false); var fontFiles = files .Select(i => new FontFile { Name = i.Name, Size = i.Length, DateCreated = _fileSystem.GetCreationTimeUtc(i), DateModified = _fileSystem.GetLastWriteTimeUtc(i) }) .OrderBy(i => i.Size) .ThenBy(i => i.Name) .ThenByDescending(i => i.DateModified) .ThenByDescending(i => i.DateCreated); // max total size 20M const int MaxSize = 20971520; var sizeCounter = 0L; foreach (var fontFile in fontFiles) { sizeCounter += fontFile.Size; if (sizeCounter >= MaxSize) { _logger. LogWarning("Some fonts will not be sent due to size limitations"); yield break; } yield return fontFile; } } else { _logger. LogWarning("The path of fallback font folder has not been set"); encodingOptions.EnableFallbackFont = false; } }
-
If the current character can be rendered by the first font, use it to render the current character, or use the next font in the list to render; -
If the font in the whole list does not contain this character, try to use the default font to render the character (note that the resource organization form of the front-end plug-in in this version is different from that of the general version, which will be discussed later); -
If the default font still cannot render the character, an error is reported.
#Zimiao.com fork from github/jellyfin/JavascriptSubtitlesOctopus dist: src/subtitles-octopus-worker.bc dist/js/subtitles-octopus-worker.js dist/js/subtitles-octopus-worker-legacy.js dist/js/subtitles-octopus.js dist/js/COPYRIGHT dist/js/default.woff2 dist/js/subtitles-octopus-worker.js: src/subtitles-octopus-worker.bc src/pre-worker.js src/SubOctpInterface.js src/post-worker.js build/lib/brotli/js/decode.js mkdir -p dist/js emcc src/subtitles-octopus-worker.bc $(OCTP_DEPS) \ --pre-js src/pre-worker.js \ --pre-js build/lib/brotli/js/decode.js \ --post-js src/SubOctpInterface.js \ --post-js src/post-worker.js \ -s WASM=1 \ $(EMCC_COMMON_ARGS)
-
Replace and repackage Jellyfin customized JavascriptSubtitlesOctopus; -
The Fallback directory directly points to System Font; -
Provide a all-in-one font to put in the Fallback directory;
Solution: Use the all-in-one font as the rendering font
github: adobe-fonts/source-han-sans Siyuan boldface is a set of OpenType/CFF pan Chinese Japanese Korean fonts. This open source project not only provides available OpenType fonts, All source files for creating these OpenType fonts using AFDKO tools are also provided.
Other issues