Allow apps to provide a TypefaceFactory for subtitles (e.g. for tts:fontFamily referencing a font in the app's assets directory)
How can I configure exoplayer to use a custom font for subtitles, when the font name is referenced within the TTML sample? The font is not already installed on the users device and would be distributed via the assets directory.
So given:
-
a ttf inside my assets directory:
-
The font is referenced inside a TTML sample's tts:fontFamily attribute, eg:
<head>
<styling>
<style tts:fontFamily="ReithSans, proportionalSansSerif, SansSerif, default" xml:id="textStyle" />
</styling>
</head>
<body style="textStyle">
<p>custom font appears here</p>
...
how best can I make sure ReithSans is used in the resulting Cues?
--
I note that TtmlRenderUtil is using TypefaceSpan(String fontFamily) rather than TypefaceSpan(Typeface typeface). I can see from breakpoints that the cues contain a TypefaceSpan with the string description of font families, including ReithSans, but from my understanding of Typeface this will be used to locate system fonts rather than fonts in the assets directory.
My current workaround is to intercept cues and replace the TypefaceSpan manually when adding a TextOutput:
fun attachSubtitlesView(subtitleView: SubtitleView) {
simpleExoplayer.addTextOutput { cues ->
val cuesWithFixedStyling = cues.map { it.applyTypefaceSpan(typeface) }
subtitleView.onCues(cuesWithFixedStyling)
}
}
private fun Cue.applyCustomSpans(typeface: Typeface): Cue {
val text = this.text as? SpannableStringBuilder
?: return this
val spanToReplace = text
.getSpans(0, text.length, TypefaceSpan::class.java)
.firstOrNull()
?: return this
text.removeSpan(spanToReplace)
text.setSpan(TypefaceSpan(typeface), 0, text.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
return this.buildUpon()
.setText(text)
.build()
}
but I would prefer not to have to recreate cues like this.
Is there a better approach?
--
I am using exoplayer 2.12.0 but have linked to TtmlRenderUtil in androidx/media above.
I don't think there's a better way to achieve what you're doing at the moment.
If I understand correctly, the app needs to be involved at some point in mapping the string from the TTML file to a Typeface object (since the app knows how to build a Typeface from its assets directory), which can then be passed to TypefaceSpan - is that right? In that case, I think a possible cleaner approach (requiring changes to the library) would be to take a TypefaceFactory (we would define this type) as an optional parameter to TtmlDecoder, and then plumb this through to be used in TtmlRenderUtil where we construct the TypefaceSpan.
If you'd like to make this change I think we'd accept it as a high quality PR, but we're unlikely to make it ourselves.
Thanks for the speedy response. We'll consider raising a PR as suggested.
is there a way to add multiple text at specific time using this library? like custom captions?. Currently Im able to add just one text following this video https://youtu.be/7vmiYP4vNUE
is there a way to add multiple text at specific time using this library? like custom captions?. Currently Im able to add just one text following this video https://youtu.be/7vmiYP4vNUE
This doesn't seem directly related to this issue. Please file a new question on the issue tracker, with more detail on why the existing methods for providing timed text (subtitles) don't suit your needs - thanks.