audioplayers: ^4.0.1
在我的 flutter 应用程序中播放本地和 url 的音频。要从本地选择文件,我使用 file_picker: ^5.2.10
。要播放本地音频,我使用的是 BytesSource()
。它在 android 中工作正常,但在 web 中抛出以下错误。我做错了什么?
错误:
Error: UnimplementedError
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49 throw_
packages/audioplayers_web/audioplayers_web.dart 118:5 setSourceBytes
packages/audioplayers/src/audioplayer.dart 318:22 setSourceBytes
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50 <fn>
dart-sdk/lib/async/zone.dart 1653:54 runUnary
dart-sdk/lib/async/future_impl.dart 147:18 handleValue
dart-sdk/lib/async/future_impl.dart 766:44 handleValueCallback
dart-sdk/lib/async/future_impl.dart 795:13 _propagateToListeners
dart-sdk/lib/async/future_impl.dart 430:9 callback
dart-sdk/lib/async/schedule_microtask.dart 40:11 _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5 _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15 <fn>
代码:
Future<void> updatingAudio() async {
audioFile = await FilePicker.platform.pickFiles(
withData: true,
type: FileType.audio,
allowCompression: true,
);
if (audioFile != null) {
audioPlayer.setSource(BytesSource(audioFile!.files.first.bytes!));
}
update();
}
这个可以完美地播放网络中本地存储中的音频。通过使用 just_audio 包。
自定义类:
import 'package:just_audio/just_audio.dart';
class MyCustomSource extends StreamAudioSource {
final List<int> bytes;
final String type;
MyCustomSource({required this.bytes, required this.type});
@override
Future<StreamAudioResponse> request([int? start, int? end]) async {
start ??= 0;
end ??= bytes.length;
return StreamAudioResponse(
sourceLength: bytes.length,
contentLength: end - start,
offset: start,
stream: Stream.value(bytes.sublist(start, end)),
contentType: type,
);
}
}
选择本地文件
Future<void> selectingAudio() async {
audioFile = await FilePicker.platform.pickFiles(
withData: true,
type: FileType.audio,
allowCompression: true,
);
if (audioFile != null) {
try {
String mimetype = "audio/";
if (audioFile!.files.first.extension != null) {
mimetype = mimetype + audioFile!.files.first.extension!;
} else {
mimetype = "${mimetype}mp3";
}
await audioPlayer
.setAudioSource(MyCustomSource(bytes: audioFile!.files.first.bytes as List<int>, type: mimetype));
await audioPlayer.load();
Duration? duration = await audioPlayer.durationFuture;
duration ??= Duration.zero;
if (isPlaying) {
audioPlayer.stop();
isPlaying = false;
}
audioStartTime = "00:00";
audioEndTime =
"${duration.inMinutes.remainder(60).toString().padLeft(2, "0")}:${duration.inSeconds.remainder(60).toString().padLeft(2, "0")}";
} catch (exception, stacktree) {
debugPrint("$exception");
debugPrint("$stacktree");
}
}
}
正如 Wh1t3rabbit 所评论的那样,
setSourceBytes
未在多个平台上实现。此线程中发布了针对网络的解决方法:https://github.com/bluefireteam/audioplayers/issues/1269#issuecomment-1434089114
示例:
UrlSource urlSourceFromBytes(Uint8List bytes,{String mimeType= "audio/mpeg"}) {
return UrlSource(Uri.dataFromBytes(bytes, mimeType: mimeType).toString());
}
Future<void> updatingAudio() async {
audioFile = await FilePicker.platform.pickFiles(
withData: true,
type: FileType.audio,
allowCompression: true,
);
if (audioFile != null) {
audioPlayer.setSource(urlSourceFromBytes(audioFile!.files.first.bytes!));
}
update();
}