From ccd8ec16bb3c6a6aa57f1ecc264ca19b7e801fc9 Mon Sep 17 00:00:00 2001 From: Shuming Liu Date: Wed, 26 Aug 2026 09:08:38 +0800 Subject: [PATCH] fixed a bug --- .../oraltrainer/sample/MainActivity.kt | 98 +++++++++++++++++-- 1 file changed, 89 insertions(+), 9 deletions(-) diff --git a/android/sample-app/src/main/java/cn/learningpad/oraltrainer/sample/MainActivity.kt b/android/sample-app/src/main/java/cn/learningpad/oraltrainer/sample/MainActivity.kt index a301ce4..e9aeb75 100644 --- a/android/sample-app/src/main/java/cn/learningpad/oraltrainer/sample/MainActivity.kt +++ b/android/sample-app/src/main/java/cn/learningpad/oraltrainer/sample/MainActivity.kt @@ -93,7 +93,7 @@ class MainActivity : Activity() { private val mainHandler = Handler(Looper.getMainLooper()) private var mediaRecorder: MediaRecorder? = null private var recordingFile: File? = null - private val dubSegments = mutableListOf() + private val dubSegments = mutableMapOf() private var mergedDubFile: File? = null private var dubbingPlayback = false @@ -103,6 +103,7 @@ class MainActivity : Activity() { private var catalogStatusTextValue = "正在同步" private var activeModule = Module.TRAIN private var continuousPlaybackEnabled = false + private var testSubtitleVisible = false private var landscapeSubtitleVisible = true private val screenActionReceiver = object : BroadcastReceiver() { @@ -298,8 +299,12 @@ class MainActivity : Activity() { return LinearLayout(this).apply { orientation = LinearLayout.VERTICAL setBackgroundColor(COLOR_BACKGROUND) - addView(createPlayerSection()) - addView(createSentenceSection()) + if (testSubtitleVisible) { + addView(createPlayerSection()) + addView(createSentenceSection()) + } else { + addView(createPlayerSection()) + } addView(createTestSection()) } } @@ -334,8 +339,9 @@ class MainActivity : Activity() { } activeModule = module controller.setContinuousPlayback( - if (activeModule == Module.TRAIN) continuousPlaybackEnabled else true + if (activeModule == Module.TRAIN) continuousPlaybackEnabled else false ) + landscapeSubtitleVisible = activeModule == Module.TRAIN || testSubtitleVisible setContentView(createContentView()) renderCatalog() refreshCurrentUi() @@ -767,6 +773,30 @@ class MainActivity : Activity() { } } + val subtitleToggle = LinearLayout(this).apply { + orientation = LinearLayout.HORIZONTAL + gravity = Gravity.CENTER_VERTICAL + setPadding(0, 10.dp, 0, 0) + addView(TextView(this@MainActivity).apply { + text = "显示字幕" + setTextColor(COLOR_TEXT_DARK) + textSize = 13f + typeface = Typeface.DEFAULT_BOLD + layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f) + }) + addView(Switch(this@MainActivity).apply { + isChecked = testSubtitleVisible + buttonTintList = ColorStateList.valueOf(COLOR_ACCENT) + setOnCheckedChangeListener { _, checked -> + testSubtitleVisible = checked + landscapeSubtitleVisible = checked + setContentView(createContentView()) + refreshCurrentUi() + refreshTestUi() + } + }) + } + playDubButton = dubButton("播放配音", {}).apply { isEnabled = false } mergeDubButton = dubButton("生成配音", {}).apply { isEnabled = false } shareDubButton = dubButton("分享配音", {}).apply { isEnabled = false } @@ -798,6 +828,7 @@ class MainActivity : Activity() { textSize = 16f typeface = Typeface.DEFAULT_BOLD }) + addView(subtitleToggle, 0) addView(testStatusText) addView(controlRow) addView(recordButton) @@ -816,10 +847,15 @@ class MainActivity : Activity() { if (!::testStatusText.isInitialized) { return } + applyTestSubtitleVisibility() recordButton.text = if (mediaRecorder == null) "开始录音" else "停止并评测" - val segmentLabel = if (dubSegments.isEmpty()) "" else " · 已保存 ${dubSegments.size} 段" val item = controller.currentTrainingItem() val sentence = controller.currentSentence() + val currentRecording = sentence?.let { dubSegments[it.index] } + val segmentLabel = when { + currentRecording != null -> " · 本句已录音,重录将覆盖" + else -> "" + } testStatusText.text = if (item == null || sentence == null) { "请先在训练模块选择课程$segmentLabel" } else { @@ -828,6 +864,20 @@ class MainActivity : Activity() { refreshDubButtons() } + private fun applyTestSubtitleVisibility() { + if (activeModule != Module.TEST) { + return + } + landscapeSubtitleVisible = testSubtitleVisible + if (!::sentenceText.isInitialized || !::progressBar.isInitialized) { + return + } + val visibility = if (testSubtitleVisible) View.VISIBLE else View.GONE + sentenceMetaText.visibility = visibility + sentenceText.visibility = visibility + progressBar.visibility = visibility + } + private fun startRecording() { controller.pause() if (!::testStatusText.isInitialized) { @@ -853,10 +903,20 @@ class MainActivity : Activity() { recorder.setOutputFile(file.absolutePath) recorder.prepare() recorder.start() + val sentence = controller.currentSentence() + if (sentence != null) { + controller.seekTo(sentence.startMs) + controller.setVolume(0f) + } + controller.play() mediaRecorder = recorder recordingFile = file recordButton.text = "停止并保存" - testStatusText.text = "正在录音…读完当前句子后点击“停止并保存”" + testStatusText.text = if (sentence == null) { + "正在录音…读完当前句子后点击“停止并保存”" + } else { + "正在录音…请对照静音视频口形,读完点击“停止并保存”" + } } catch (error: Throwable) { testStatusText.text = "录音启动失败:${error.message.orEmpty()}" runCatching { recorder.release() } @@ -878,7 +938,18 @@ class MainActivity : Activity() { } finally { runCatching { recorder.release() } } - dubSegments.add(file) + controller.pause() + controller.setVolume(1f) + val sentenceIndex = controller.currentSentence()?.index + if (sentenceIndex == null) { + testStatusText.text = "没有可归属的句子,本次录音已丢弃" + file.delete() + recordingFile = null + refreshTestUi() + return + } + dubSegments[sentenceIndex]?.delete() + dubSegments[sentenceIndex] = file mergedDubFile = null recordingFile = null submitAssessment(Uri.fromFile(file)) @@ -907,9 +978,11 @@ class MainActivity : Activity() { playDubButton.isEnabled = dubSegments.isNotEmpty() && !dubbingPlayback mergeDubButton.isEnabled = dubSegments.size >= 2 && !dubbingPlayback shareDubButton.isEnabled = mergedDubFile?.exists() == true && !dubbingPlayback + val activeAudio = controller.currentSentence()?.let { dubSegments[it.index] } playDubButton.text = when { dubbingPlayback -> "停止配音" mergedDubFile?.exists() == true -> "播放配音" + activeAudio != null -> "播放本句配音" else -> "播放录音(${dubSegments.size})" } } @@ -919,7 +992,14 @@ class MainActivity : Activity() { stopDubPlayback("已停止配音播放") return } - startDubPlayback(mergedDubFile ?: dubSegments.lastOrNull() ?: return) + startDubPlayback(mergedDubFile ?: activeAudioForPlayback() ?: return) + } + + private fun activeAudioForPlayback(): File? { + if (mergedDubFile != null) { + return mergedDubFile + } + return controller.currentSentence()?.let { sentence -> dubSegments[sentence.index] } } private fun startDubPlayback(audioFile: File) { @@ -978,7 +1058,7 @@ class MainActivity : Activity() { var muxerAudioTrack = -1 var presentationTimeUs = 0L - dubSegments.forEach { segment -> + dubSegments.toSortedMap().values.forEach { segment -> val extractor = MediaExtractor().apply { setDataSource(segment.absolutePath) } try { val trackIndex = (0 until extractor.trackCount).firstOrNull { index ->