瀏覽代碼

[new]增加音频播放功能

zk 1 年之前
父節點
當前提交
dc241f471b
共有 5 個文件被更改,包括 103 次插入11 次删除
  1. 3 1
      assets/string/base/string.xml
  2. 80 5
      lib/module/talk/controller.dart
  3. 7 5
      lib/module/talk/view.dart
  4. 10 0
      lib/utils/expand.dart
  5. 3 0
      pubspec.yaml

+ 3 - 1
assets/string/base/string.xml

@@ -40,7 +40,8 @@
     <string name="talk_rename_title_hint">请输入谈话记录标题</string>
     <string name="talk_rename_success">修改成功</string>
     <string name="talk_rename_fail">修改失败</string>
-    <string name="talk_rename_delete_prompt">是否删除“%s”模板?该谈话包含您的待办事项,将一并删除。</string>
+    <string name="talk_rename_delete_prompt">是否删除“%s”模板?该谈话包含您的待办事项,将一并删除。
+    </string>
     <string name="talk_delete_success">删除成功</string>
     <string name="talk_delete_fail">删除失败</string>
     <string name="talk_tab_summary">谈话总结</string>
@@ -67,4 +68,5 @@
     </string>
     <string name="talk_traffic_remind_tips">以后不再提示</string>
     <string name="talk_upload_file_not_exist">文件不存在</string>
+    <string name="talk_audio_loading">音频正在加载中</string>
 </resources>

+ 80 - 5
lib/module/talk/controller.dart

@@ -23,6 +23,7 @@ import '../../dialog/alert_dialog.dart';
 import '../../utils/toast_util.dart';
 import '../record/controller.dart';
 import 'original/view.dart';
+import 'package:just_audio/just_audio.dart';
 
 class TalkController extends BaseController {
   final String uploadNoPrompts = "UPLOAD_NO_PROMPTS";
@@ -31,10 +32,16 @@ class TalkController extends BaseController {
 
   final isShowElectricLow = false.obs;
 
+  bool isAudioLoading = false;
+
+  final double sliderMax = 1;
+
   final isAudioPlaying = false.obs;
 
   final audioProgressValue = 0.0.obs;
 
+  final audioDuration = Duration.zero.obs;
+
   final agendaAllList = <AgendaListAllBean>[].obs;
 
   final List<String> tabBeans = [
@@ -43,6 +50,8 @@ class TalkController extends BaseController {
     StringName.talkTabOriginal.tr
   ];
 
+  final _audioPlayer = AudioPlayer();
+
   StreamSubscription? _talkBeanListener;
 
   final pages = [const SummaryView(), const TodoView(), const OriginalView()];
@@ -50,17 +59,66 @@ class TalkController extends BaseController {
   @override
   void onReady() {
     super.onReady();
+    _initAudioPlayer();
     _initListener();
     _getArguments();
   }
 
+  void _initAudioPlayer() {
+    _audioPlayer.playerStateStream.listen((playerState) {
+      if (playerState.processingState == ProcessingState.loading ||
+          playerState.processingState == ProcessingState.buffering) {
+        isAudioLoading = true;
+        debugPrint('音频load = true');
+      } else {
+        debugPrint('音频load = false');
+        isAudioLoading = false;
+        if (playerState.processingState == ProcessingState.completed) {
+          _audioPlayer.stop();
+          _audioPlayer.seek(Duration.zero);
+          isAudioPlaying.value = false;
+          debugPrint('音频 播放结束了');
+        }
+      }
+      isAudioPlaying.value = playerState.playing;
+    }, onError: (Object e, StackTrace stackTrace) {
+      debugPrint('音频加载异常 == $e');
+    });
+
+    _audioPlayer.durationStream.listen((duration) {
+      if (duration != null) {
+        debugPrint('音频总播放时长 == ${duration.inMilliseconds}');
+        audioDuration.value = duration;
+      }
+    });
+
+    _audioPlayer.positionStream.listen((position) {
+      if (audioDuration.value.inMilliseconds > 0) {
+        audioProgressValue.value =
+            (position.inMilliseconds / audioDuration.value.inMilliseconds)
+                .clamp(0.0, sliderMax);
+      }
+    });
+  }
+
   void _initListener() {
     _talkBeanListener = talkBean.listen((bean) {
       _dealTalkUpdate(bean);
     });
   }
 
-  void _dealTalkUpdate(TalkBean? bean) {}
+  void _dealTalkUpdate(TalkBean? bean) async {
+    String? id = talkBean.value?.id;
+    if (id == null) {
+      return;
+    }
+    try {
+      File file = await RecordController.getRecordFile(id);
+      await _audioPlayer.setAudioSource(AudioSource.uri(file.uri));
+    } catch (e) {
+      debugPrint('音频设置异常 == $e');
+    }
+  }
 
   void _getArguments() {
     if (Get.arguments is TalkBean) {
@@ -68,6 +126,26 @@ class TalkController extends BaseController {
     }
   }
 
+  void updateProgress(double value) {
+    final newPosition = Duration(
+        milliseconds: (value * audioDuration.value.inMilliseconds).toInt());
+    _audioPlayer.seek(newPosition);
+  }
+
+  void clickPlayAudio() {
+    if (isAudioLoading) {
+      ToastUtil.showToast(StringName.talkAudioLoading.tr);
+      return;
+    }
+    if (_audioPlayer.playing) {
+      _audioPlayer.pause();
+      isAudioPlaying.value = false;
+    } else {
+      _audioPlayer.play();
+      isAudioPlaying.value = true;
+    }
+  }
+
   void _checkFileSizeAndNet() async {
     String? id = talkBean.value?.id;
     if (id == null) {
@@ -211,9 +289,6 @@ class TalkController extends BaseController {
   void onClose() {
     super.onClose();
     _talkBeanListener?.cancel();
-  }
-
-  void updateProgress(double value) {
-    audioProgressValue.value = value;
+    _audioPlayer.dispose();
   }
 }

+ 7 - 5
lib/module/talk/view.dart

@@ -285,7 +285,7 @@ class TalkPage extends BasePage<TalkController> {
           SizedBox(width: 9.w),
           GestureDetector(
             onTap: () {
-              // controller.playAudio();
+              controller.clickPlayAudio();
             },
             child: Obx(() {
               return SizedBox(
@@ -314,7 +314,7 @@ class TalkPage extends BasePage<TalkController> {
                   child: Slider(
                     value: controller.audioProgressValue.value,
                     min: 0.0,
-                    max: 1.0,
+                    max: controller.sliderMax,
                     onChanged: (value) {
                       controller.updateProgress(value);
                     },
@@ -324,9 +324,11 @@ class TalkPage extends BasePage<TalkController> {
             );
           }),
           SizedBox(width: 11.w),
-          Text('3:21',
-              style: TextStyle(
-                  fontSize: 10.sp, color: ColorName.secondaryTextColor))
+          Obx(() {
+            return Text(controller.audioDuration.value.toFormattedString(),
+                style: TextStyle(
+                    fontSize: 10.sp, color: ColorName.secondaryTextColor));
+          })
         ],
       ),
     );

+ 10 - 0
lib/utils/expand.dart

@@ -75,3 +75,13 @@ extension FileSizeExtension on int {
     }
   }
 }
+
+extension DurationFormatting on Duration {
+  String toFormattedString() {
+    String twoDigits(int n) => n.toString().padLeft(2, '0');
+    String hours = twoDigits(inHours);
+    String minutes = twoDigits(inMinutes.remainder(60));
+    String seconds = twoDigits(inSeconds.remainder(60));
+    return [if (inHours > 0) hours, minutes, seconds].join(':');
+  }
+}

+ 3 - 0
pubspec.yaml

@@ -72,6 +72,9 @@ dependencies:
   #网络连接类型
   connectivity_plus: ^6.0.5
 
+  #音频播放
+  just_audio: ^0.9.40
+
 dev_dependencies:
   flutter_test:
     sdk: flutter