Flutter音频播放插件just_audio的使用

发布于 1周前 作者 songsunli 来自 Flutter

Flutter音频播放插件just_audio的使用

简介

just_audio 是一个功能丰富的音频播放器,适用于Android、iOS、macOS、Web、Linux和Windows平台。它提供了多种功能,包括从URL、文件、资产或字节流读取音频,支持DASH、HLS等流媒体协议,处理ICy元数据,以及更多高级特性如播放列表管理、无缝播放、循环播放、随机播放等。

快速概览

import 'package:just_audio/just_audio.dart';

void main() async {
  final player = AudioPlayer(); // 创建播放器
  await player.setUrl('https://foo.com/bar.mp3'); // 加载URL
  player.play(); // 播放
  await player.pause(); // 暂停
  await player.seek(Duration(seconds: 10)); // 跳到10秒位置
  await player.setSpeed(2.0); // 设置两倍速播放
  await player.setVolume(0.5); // 设置半音量
  await player.stop(); // 停止并释放资源
}

处理多个播放器

final player1 = AudioPlayer();
await player1.setUrl('...');
final player2 = AudioPlayer();
await player2.setUrl('...');

// 同时播放两个播放器
player1.play();
player2.play();

// 依次播放
await player1.play();
await player2.play();

// 循环播放player1直到player2结束
await player1.setLoopMode(LoopMode.one);
player1.play();
await player2.play();
await player1.pause();

// 释放资源
await player1.stop();
await player2.stop();

处理片段

await player.setClip(start: Duration(seconds: 2), end: Duration(seconds: 4));
await player.play();
await player.pause();
await player.setClip(start: Duration(seconds: 10), end: Duration(seconds: 12));
await player.play();
await player.pause();
await player.setClip(); // 清除片段区域

处理播放列表

final playlist = ConcatenatingAudioSource(
  useLazyPreparation: true,
  shuffleOrder: DefaultShuffleOrder(),
  children: [
    AudioSource.uri(Uri.parse('https://example.com/track1.mp3')),
    AudioSource.uri(Uri.parse('https://example.com/track2.mp3')),
    AudioSource.uri(Uri.parse('https://example.com/track3.mp3')),
  ],
);

await player.setAudioSource(playlist, initialIndex: 0, initialPosition: Duration.zero);
await player.seekToNext(); // 跳到下一曲
await player.seekToPrevious(); // 跳到上一曲
await player.seek(Duration.zero, index: 2); // 跳到track3.mp3的开头
await player.setLoopMode(LoopMode.all); // 设置播放列表循环
await player.setShuffleModeEnabled(true); // 打乱播放列表顺序

// 更新播放列表
await playlist.add(newChild1);
await playlist.insert(3, newChild2);
await playlist.removeAt(3);

示例代码:完整的Flutter应用示例

import 'package:audio_session/audio_session.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:just_audio/just_audio.dart';
import 'package:rxdart/rxdart.dart';

void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> with WidgetsBindingObserver {
  final _player = AudioPlayer();

  @override
  void initState() {
    super.initState();
    ambiguate(WidgetsBinding.instance)!.addObserver(this);
    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
      statusBarColor: Colors.black,
    ));
    _init();
  }

  Future<void> _init() async {
    final session = await AudioSession.instance;
    await session.configure(const AudioSessionConfiguration.speech());
    _player.playbackEventStream.listen((event) {}, onError: (Object e, StackTrace stackTrace) {
      print('A stream error occurred: $e');
    });
    try {
      await _player.setAudioSource(AudioSource.uri(Uri.parse(
          "https://s3.amazonaws.com/scifri-episodes/scifri20181123-episode.mp3")));
    } on PlayerException catch (e) {
      print("Error loading audio source: $e");
    }
  }

  @override
  void dispose() {
    ambiguate(WidgetsBinding.instance)!.removeObserver(this);
    _player.dispose();
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.paused) {
      _player.stop();
    }
  }

  Stream<PositionData> get _positionDataStream =>
      Rx.combineLatest3<Duration, Duration, Duration?, PositionData>(
          _player.positionStream,
          _player.bufferedPositionStream,
          _player.durationStream,
          (position, bufferedPosition, duration) => PositionData(
              position, bufferedPosition, duration ?? Duration.zero));

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ControlButtons(_player),
              StreamBuilder<PositionData>(
                stream: _positionDataStream,
                builder: (context, snapshot) {
                  final positionData = snapshot.data;
                  return SeekBar(
                    duration: positionData?.duration ?? Duration.zero,
                    position: positionData?.position ?? Duration.zero,
                    bufferedPosition: positionData?.bufferedPosition ?? Duration.zero,
                    onChangeEnd: _player.seek,
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class ControlButtons extends StatelessWidget {
  final AudioPlayer player;

  const ControlButtons(this.player, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        IconButton(
          icon: const Icon(Icons.volume_up),
          onPressed: () {
            showSliderDialog(
              context: context,
              title: "Adjust volume",
              divisions: 10,
              min: 0.0,
              max: 1.0,
              value: player.volume,
              stream: player.volumeStream,
              onChanged: player.setVolume,
            );
          },
        ),
        StreamBuilder<PlayerState>(
          stream: player.playerStateStream,
          builder: (context, snapshot) {
            final playerState = snapshot.data;
            final processingState = playerState?.processingState;
            final playing = playerState?.playing;
            if (processingState == ProcessingState.loading ||
                processingState == ProcessingState.buffering) {
              return Container(
                margin: const EdgeInsets.all(8.0),
                width: 64.0,
                height: 64.0,
                child: const CircularProgressIndicator(),
              );
            } else if (playing != true) {
              return IconButton(
                icon: const Icon(Icons.play_arrow),
                iconSize: 64.0,
                onPressed: player.play,
              );
            } else if (processingState != ProcessingState.completed) {
              return IconButton(
                icon: const Icon(Icons.pause),
                iconSize: 64.0,
                onPressed: player.pause,
              );
            } else {
              return IconButton(
                icon: const Icon(Icons.replay),
                iconSize: 64.0,
                onPressed: () => player.seek(Duration.zero),
              );
            }
          },
        ),
        StreamBuilder<double>(
          stream: player.speedStream,
          builder: (context, snapshot) => IconButton(
            icon: Text("${snapshot.data?.toStringAsFixed(1)}x",
                style: const TextStyle(fontWeight: FontWeight.bold)),
            onPressed: () {
              showSliderDialog(
                context: context,
                title: "Adjust speed",
                divisions: 10,
                min: 0.5,
                max: 1.5,
                value: player.speed,
                stream: player.speedStream,
                onChanged: player.setSpeed,
              );
            },
          ),
        ),
      ],
    );
  }
}

总结

just_audio 插件为Flutter开发者提供了一个强大且易于使用的音频播放解决方案。通过上述示例代码和详细说明,您可以快速上手并在您的项目中集成音频播放功能。如果您需要更高级的功能,如后台播放、音频会话配置等,可以参考官方文档和相关教程。


更多关于Flutter音频播放插件just_audio的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter音频播放插件just_audio的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用just_audio插件进行音频播放的代码示例。just_audio是一个功能强大且灵活的音频播放插件,适用于需要精细控制音频播放的应用。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加just_audio依赖:

dependencies:
  flutter:
    sdk: flutter
  just_audio: ^0.9.15  # 请检查最新版本号

2. 导入包

在你的Dart文件中导入just_audio包:

import 'package:just_audio/just_audio.dart';
import 'package:flutter/material.dart';

3. 创建AudioPlayer实例

在你的Flutter组件中创建一个AudioPlayer实例:

class AudioPlayerScreen extends StatefulWidget {
  @override
  _AudioPlayerScreenState createState() => _AudioPlayerScreenState();
}

class _AudioPlayerScreenState extends State<AudioPlayerScreen> {
  late AudioPlayer audioPlayer;

  @override
  void initState() {
    super.initState();
    audioPlayer = AudioPlayer();
  }

  @override
  void dispose() {
    audioPlayer.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Just Audio Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () async {
                // 替换为你的音频URL
                final url = 'https://example.com/audiofile.mp3';
                await audioPlayer.setUrl(url);
                await audioPlayer.play();
              },
              child: Text('Play Audio'),
            ),
            ElevatedButton(
              onPressed: () {
                audioPlayer.pause();
              },
              child: Text('Pause Audio'),
            ),
            ElevatedButton(
              onPressed: () {
                audioPlayer.stop();
              },
              child: Text('Stop Audio'),
            ),
          ],
        ),
      ),
    );
  }
}

4. 监听播放状态(可选)

你可以监听音频播放器的状态变化,例如播放进度、缓冲状态等。以下是如何添加这些监听器的示例:

class _AudioPlayerScreenState extends State<AudioPlayerScreen> {
  late AudioPlayer audioPlayer;
  late PositionInformation? positionInformation;
  late bool isPlaying = false;

  @override
  void initState() {
    super.initState();
    audioPlayer = AudioPlayer();

    // 监听播放位置变化
    audioPlayer.positionStream.listen((position) {
      setState(() {
        positionInformation = position;
      });
    });

    // 监听播放状态变化
    audioPlayer.playingStream.listen((playing) {
      setState(() {
        isPlaying = playing;
      });
    });
  }

  @override
  void dispose() {
    audioPlayer.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Just Audio Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () async {
                final url = 'https://example.com/audiofile.mp3';
                await audioPlayer.setUrl(url);
                await audioPlayer.play();
              },
              child: Text('Play Audio'),
            ),
            ElevatedButton(
              onPressed: () {
                audioPlayer.pause();
              },
              child: Text('Pause Audio'),
            ),
            ElevatedButton(
              onPressed: () {
                audioPlayer.stop();
              },
              child: Text('Stop Audio'),
            ),
            if (positionInformation != null)
              Text('Current Position: ${positionInformation!.position.inMilliseconds}ms'),
            Text('Is Playing: $isPlaying'),
          ],
        ),
      ),
    );
  }
}

以上代码展示了如何使用just_audio插件进行基本的音频播放控制,并监听播放位置和播放状态。你可以根据需要进一步扩展这些功能,例如添加音量控制、进度条等。

回到顶部