如何在Android中异步同时播放视频和音频

How to play Video & Audio in the same time, asynchronously in Android

提问人:Theseus 提问时间:11/9/2022 最后编辑:Theseus 更新时间:11/15/2022 访问量:119

问:

我正在尝试为锻炼 android 应用程序实现以下内容:

  1. 设置倒数计时器并倒计时时间(例如从 30 秒到 0)。
  2. 从计时器启动的那一刻起,可重复的锻炼静音视频开始循环播放,直到计时器达到 0,下一个锻炼视频出现,计时器重置为 30 再次倒计时。
  3. 当计时器运行时,音频与视频同时播放,以向用户指示各种内容(即。“开始锻炼”、“3-2-1”、“下一个锻炼”等)

我的问题是,如何将视频与音频相结合?对于视频,我使用ExoPlayer。将 ExoPlayer 与 SoundPool for Audio 结合使用好吗?我是否应该为两者创建多个 ExoPlayer 实例(如果是这样,我应该将 AudioPlayer 实例绑定到什么)?

Android ExoPlayer 音池

评论


答:

0赞 Theseus 11/15/2022 #1

,我发现最好的解决方案是将 ExoPlayer 用于视频,并使用 SoundPool 进行简短的音频语音指示。

我使用一个观察器函数,在该函数中我监听计时器事件(即 tick == 4000),并在每次事件发生时使用 soundPool.play()。

对于视频,我收听计时器事件(PLAYING、PAUSED、STOPPED)并使用 videoPlayer.play()。

请参阅下面的代码作为示例:

    private fun subscribeObservers() {
    viewLifecycleOwner.lifecycleScope.launch {
        viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {

            launch {
                sharedViewModel.timer.tick.collect { tick ->
                    // tick can only be multiple of 1000
                    if (tick == 0L) {
                        binding.startWorkoutTvTimer.text = ""
                    } else {
                        binding.startWorkoutTvTimer.text = (tick / 1000).toString()
                    }

                    if (tick == 4000L) {
                        sharedViewModel.soundPool?.play(sharedViewModel.countdownSoundId, 1F, 1F, 0, 0, 1F)
                    }

                    // SoundPool needs to be preloaded from previous Fragment
                    if (tick == 10000L) {
                        if (sharedViewModel.currentExercise == 0) {
                            sharedViewModel.soundPool?.play(sharedViewModel.beginWorkoutSoundId, 1F, 1F, 1, 0, 1F)

                        } else {
                            sharedViewModel.soundPool?.play(sharedViewModel.goSoundId, 1F, 1F, 1, 0, 1F)
                        }

                    }
                }
            }


            launch {
                sharedViewModel.timer.timerMode.collect { playerMode ->
                    when (playerMode) {
                        TimerMode.PLAYING -> {
                            binding.startWorkoutBtnPause.setBackgroundResource(R.drawable.ic_baseline_pause_24)
                            videoPlayer?.play()
                        }

                        TimerMode.PAUSED -> {
                            binding.startWorkoutBtnPause.setBackgroundResource(R.drawable.ic_baseline_play_arrow_24)
                            videoPlayer?.pause()
                        }

                        TimerMode.STOPPED -> {
                        }
                    }
                }
            }


        }

    }
}