diff --git a/modules/mpv-player/android/src/main/assets/subfont.ttf b/modules/mpv-player/android/src/main/assets/subfont.ttf new file mode 100644 index 00000000..23daaa4e Binary files /dev/null and b/modules/mpv-player/android/src/main/assets/subfont.ttf differ diff --git a/modules/mpv-player/android/src/main/java/expo/modules/mpvplayer/MPVLayerRenderer.kt b/modules/mpv-player/android/src/main/java/expo/modules/mpvplayer/MPVLayerRenderer.kt index 83260909..38c55625 100644 --- a/modules/mpv-player/android/src/main/java/expo/modules/mpvplayer/MPVLayerRenderer.kt +++ b/modules/mpv-player/android/src/main/java/expo/modules/mpvplayer/MPVLayerRenderer.kt @@ -1,10 +1,13 @@ package expo.modules.mpvplayer import android.content.Context +import android.content.res.AssetManager import android.os.Handler import android.os.Looper import android.util.Log import android.view.Surface +import java.io.File +import java.io.FileOutputStream /** * MPV renderer that wraps libmpv for video playback. @@ -102,6 +105,52 @@ class MPVLayerRenderer(private val context: Context) : MPVLib.EventObserver { MPVLib.create(context) MPVLib.addObserver(this) + /** + * Create mpv config directory and copy font files to ensure SubRip subtitles load properly on Android. + * + * Technical Background: + * ==================== + * On Android, mpv requires access to a font file to render text-based subtitles, particularly SubRip (.srt) + * format subtitles. Without an available font in the config directory, mpv will fail to display subtitles + * even when subtitle tracks are properly detected and loaded. + * + * Why This Is Necessary: + * ===================== + * 1. Android's font system is isolated from native libraries like mpv. While Android has system fonts, + * mpv cannot access them directly due to sandboxing and library isolation. + * + * 2. SubRip subtitles require a font to render text overlay on video. When no font is available in the + * configured directory, mpv either: + * - Fails silently (subtitles don't appear) + * - Falls back to a default font that may not support the required character set + * - Crashes or produces rendering errors + * + * 3. By placing a font file (font.ttf) in mpv's config directory and setting that directory via + * MPVLib.setOptionString("config-dir", ...), we ensure mpv has a known, accessible font source. + * + * Reference: + * ========= + * This workaround is documented in the mpv-android project: + * https://github.com/mpv-android/mpv-android/issues/96 + * + * The issue discusses that without a font in the config directory, SubRip subtitles fail to load + * properly on Android, and the solution is to copy a font file to a known location that mpv can access. + */ + // Create mpv config directory and copy font files + val mpvDir = File(context.getExternalFilesDir(null) ?: context.filesDir, "mpv") + //Log.i(TAG, "mpv config dir: $mpvDir") + if (!mpvDir.exists()) mpvDir.mkdirs() + // This needs to be named `subfont.ttf` else it won't work + arrayOf("subfont.ttf").forEach { fileName -> + val file = File(mpvDir, fileName) + if (file.exists()) return@forEach + context.assets + .open(fileName, AssetManager.ACCESS_STREAMING) + .copyTo(FileOutputStream(file)) + } + MPVLib.setOptionString("config", "yes") + MPVLib.setOptionString("config-dir", mpvDir.path) + // Configure mpv options before initialization (based on Findroid) MPVLib.setOptionString("vo", "gpu") MPVLib.setOptionString("gpu-context", "android") @@ -125,7 +174,7 @@ class MPVLayerRenderer(private val context: Context) : MPVLib.EventObserver { MPVLib.setOptionString("hr-seek-framedrop", "yes") // Subtitle settings - MPVLib.setOptionString("sub-scale-with-window", "yes") + MPVLib.setOptionString("sub-scale-with-window", "no") MPVLib.setOptionString("sub-use-margins", "no") MPVLib.setOptionString("subs-match-os-language", "yes") MPVLib.setOptionString("subs-fallback", "yes")