0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Android 動画字幕の初歩

Posted at

この記事では、Androidで動画字幕を実装する際の初歩の知識で調べたことをまとめる。
サンプルのリポジトリはこちら

前提

  • media3
  • 字幕ファイルのフォーマットは WebVTT

字幕の読み込み

字幕ファイルが映像と別に提供されている場合

字幕の読み込みは次の通り(Android Developers)。

val subtitle = MediaItem.SubtitleConfiguration
        .Builder(subtitleUrl.toUri())
        .setMimeType(MimeTypes.TEXT_VTT)
        .setLanguage("en")
        .setLabel("English")
        .build()

val mediaItem = MediaItem.Builder()
    .setUri(videoUrl)
    .setSubtitleConfigurations(listOf(subtitle))
    .build()

player.setMediaItem(mediaItem)

字幕ファイルがHLSで動画ストリームと同時に提供されている場合

HLSを読み込むと同時に、字幕も内部的に読み込んでくれる。
HLSの読み込みについては次の通り(Android Developers)。

// Create a player instance.
val player = ExoPlayer.Builder(context).build()
// Set the media item to be played.
player.setMediaItem(MediaItem.fromUri(hlsUri))
// Prepare the player.
player.prepare()

字幕の表示・非表示

字幕の表示・非表示の切り替えUIと、字幕UIの2つを自作するかどうかでいくつかのパターンがある。

media3-uiですべてまかなう場合

setShowSubtitleButtonを使う(Android Developers)。

PlayerView(c).apply {
    this.player = player
    setShowSubtitleButton(true)
}

字幕の表示・非表示の切り替えUIを自作する場合

PlayerViewに対して、表示・非表示の設定を伝える必要がある。
2つの方法がある。

字幕UI自体の表示・非表示を切り替える場合は、 subtitleViewにアクセスする。

PlayerView(c).apply {
    subtitleView.visibility = if(isSubtitleVisible) {
        View.VISIBLE
    } else {
        View.GONE
    }
}

または、そもそもデータソース上から字幕を消すことで、結果的に字幕を非表示にすることもできる。

player.trackSelector?.parameters?.let { params ->
    val preferredLanguage = if(isSubtitleVisible) {
        listOf("en")
    } else {
        emptyList()
    }

    player.trackSelector?.parameters = params.buildUpon()
        .setPreferredTextLanguages(*preferredLanguage.toTypedArray())
        .build()
}

字幕UIを自作する場合

字幕UIを自作する場合は、字幕の内容を取得する必要がある。
字幕ファイルの提供フォーマットがなんであれ、ExoPlayerは内部的に字幕データをパースして保持している。

字幕ひとつひとつは Cue という単位で管理されている。
playerにListenerを設定することで、適当なタイミングでCueを取得できる。

player.addListener(object: Player.Listener {
    override fun onCues(cueGroup: CueGroup) {
        super.onCues(cueGroup)
        Log.d(":memo:", cueGroup.cues.joinToString("\n") {
            "[${it.position}]L${it.line}:${it.text}"
        })
    }
})

ListenerでCueが取得できたら、あとはそのデータを使ってUIを表示すればよい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?