simple_audio_kit 1.1.0 copy "simple_audio_kit: ^1.1.0" to clipboard
simple_audio_kit: ^1.1.0 copied to clipboard

A professional, zero-config audio playback library for Flutter. Supports playlists, background playback, lock screen controls, and robust error handling out-of-the-box.

example/lib/main.dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:simple_audio_kit/simple_audio_kit.dart';

// Sample demonstration tracks
const _playlist = [
  AudioItem(
    url: 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3',
    title: 'SoundHelix Song 1',
    artist: 'SoundHelix',
    image:
        'https://images.unsplash.com/photo-1470225620780-dba8ba36b745?auto=format&fit=crop&w=500&q=60',
  ),
  AudioItem(
    url: 'https://cdn.pixabay.com/audio/2022/03/15/audio_7ce11e3b5e.mp3',
    title: 'Cinematic Atmosphere',
    artist: 'Pixabay',
    image:
        'https://images.unsplash.com/photo-1536440136628-849c177e76a1?auto=format&fit=crop&w=500&q=60',
  ),
  AudioItem(
    url: 'https://this.is.a.broken.domain.example.com/missing.mp3',
    title: 'Broken Error Test Track',
    artist: 'Error Checking System',
    image:
        'https://images.unsplash.com/photo-1520697830682-8f15eee029ae?auto=format&fit=crop&w=500&q=60',
  ),
  AudioItem(
    url: 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3',
    title: 'SoundHelix Song 3',
    artist: 'SoundHelix',
    image:
        'https://images.unsplash.com/photo-1514525253161-7a46d19cd819?auto=format&fit=crop&w=500&q=60',
  ),
];

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 1. Initialize audio wrapper
  await Audio.init();

  runApp(const SimpleAudioExampleApp());
}

class SimpleAudioExampleApp extends StatelessWidget {
  const SimpleAudioExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Simple Audio Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.deepPurple,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: const ExampleHome(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class ExampleHome extends StatefulWidget {
  const ExampleHome({super.key});

  @override
  State<ExampleHome> createState() => _ExampleHomeState();
}

class _ExampleHomeState extends State<ExampleHome> {
  StreamSubscription? _errorSub;

  @override
  void initState() {
    super.initState();
    _errorSub = Audio.errorStream.listen((e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(e.message),
            backgroundColor: Colors.redAccent,
            behavior: SnackBarBehavior.floating,
          ),
        );
      }
    });
    // Setting up the audio session natively
    Audio.playList(_playlist).then((_) {
      // Begin paused for demonstration purposes
      Audio.pause();
    });
  }

  @override
  void dispose() {
    _errorSub?.cancel();
    super.dispose();
  }

  String _formatDuration(Duration d) {
    final m = d.inMinutes.remainder(60).toString().padLeft(2, '0');
    final s = d.inSeconds.remainder(60).toString().padLeft(2, '0');
    return '$m:$s';
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Simple Audio Demo')),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // 1. Current Player UI Card
              Card(
                elevation: 4,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(16),
                ),
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    children: [
                      const Icon(
                        Icons.music_note,
                        size: 48,
                        color: Colors.deepPurpleAccent,
                      ),
                      const SizedBox(height: 16),
                      StreamBuilder<AudioPlaybackState>(
                        stream: Audio.playbackStateStream,
                        initialData: Audio.playbackStateNow,
                        builder: (context, snapshot) {
                          final state =
                              snapshot.data ?? AudioPlaybackState.stopped;
                          final isPlaying = state == AudioPlaybackState.playing;
                          return Text(
                            isPlaying ? 'Now Playing' : 'Paused / Stopped',
                            style: Theme.of(context).textTheme.titleMedium
                                ?.copyWith(
                                  fontWeight: FontWeight.bold,
                                  color: isPlaying ? Colors.greenAccent : null,
                                ),
                          );
                        },
                      ),
                      const SizedBox(height: 16),

                      // Duration Slider
                      StreamBuilder<Duration?>(
                        stream: Audio.durationStream,
                        builder: (context, durationSnap) {
                          return StreamBuilder<Duration>(
                            stream: Audio.positionStream,
                            builder: (context, positionSnap) {
                              final duration =
                                  durationSnap.data ?? Duration.zero;
                              final position =
                                  positionSnap.data ?? Duration.zero;

                              double progress = 0.0;
                              if (duration.inMilliseconds > 0) {
                                progress =
                                    position.inMilliseconds /
                                    duration.inMilliseconds;
                              }

                              return Column(
                                children: [
                                  SliderTheme(
                                    data: SliderTheme.of(context).copyWith(
                                      trackHeight: 4,
                                      thumbShape: const RoundSliderThumbShape(
                                        enabledThumbRadius: 6,
                                      ),
                                    ),
                                    child: Slider(
                                      value: progress.clamp(0.0, 1.0),
                                      activeColor: Colors.deepPurpleAccent,
                                      inactiveColor: Colors.white24,
                                      onChanged: (value) {
                                        if (duration.inMilliseconds > 0) {
                                          Audio.seek(
                                            Duration(
                                              milliseconds:
                                                  (value *
                                                          duration
                                                              .inMilliseconds)
                                                      .toInt(),
                                            ),
                                          );
                                        }
                                      },
                                    ),
                                  ),
                                  const SizedBox(height: 2),
                                  Row(
                                    mainAxisAlignment:
                                        MainAxisAlignment.spaceBetween,
                                    children: [
                                      Text(
                                        _formatDuration(position),
                                        style: Theme.of(
                                          context,
                                        ).textTheme.labelSmall,
                                      ),
                                      Text(
                                        _formatDuration(duration),
                                        style: Theme.of(
                                          context,
                                        ).textTheme.labelSmall,
                                      ),
                                    ],
                                  ),
                                ],
                              );
                            },
                          );
                        },
                      ),

                      const SizedBox(height: 24),

                      // Playback Controls
                      StreamBuilder<AudioPlaybackState>(
                        stream: Audio.playbackStateStream,
                        initialData: Audio.playbackStateNow,
                        builder: (context, snapshot) {
                          final isPlaying =
                              snapshot.data == AudioPlaybackState.playing;

                          return Row(
                            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                            children: [
                              IconButton(
                                icon: const Icon(Icons.skip_previous, size: 36),
                                onPressed: Audio.previous,
                              ),
                              FloatingActionButton(
                                elevation: 0,
                                onPressed: isPlaying
                                    ? Audio.pause
                                    : Audio.resume,
                                child: Icon(
                                  isPlaying ? Icons.pause : Icons.play_arrow,
                                  size: 32,
                                ),
                              ),
                              IconButton(
                                icon: const Icon(Icons.skip_next, size: 36),
                                onPressed: Audio.next,
                              ),
                            ],
                          );
                        },
                      ),
                    ],
                  ),
                ),
              ),

              const SizedBox(height: 16),

              // 2. Extra Controls (Repeat / Shuffle)
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  StreamBuilder<AudioRepeatMode>(
                    stream: Audio.repeatModeStream,
                    initialData: AudioRepeatMode.off,
                    builder: (context, snapshot) {
                      final mode = snapshot.data ?? AudioRepeatMode.off;
                      IconData icon;
                      Color color = Colors.grey;

                      if (mode == AudioRepeatMode.off) {
                        icon = Icons.repeat;
                      } else if (mode == AudioRepeatMode.one) {
                        icon = Icons.repeat_one;
                        color = Colors.deepPurpleAccent;
                      } else {
                        icon = Icons.repeat;
                        color = Colors.deepPurpleAccent;
                      }

                      return OutlinedButton.icon(
                        icon: Icon(icon, color: color),
                        label: const Text('Repeat'),
                        onPressed: () {
                          final nextMode = mode == AudioRepeatMode.off
                              ? AudioRepeatMode.all
                              : mode == AudioRepeatMode.all
                              ? AudioRepeatMode.one
                              : AudioRepeatMode.off;
                          Audio.setRepeatMode(nextMode);
                        },
                      );
                    },
                  ),
                  StreamBuilder<bool>(
                    stream: Audio.shuffleStream,
                    initialData: false,
                    builder: (context, snapshot) {
                      final isShuffled = snapshot.data ?? false;
                      return OutlinedButton.icon(
                        icon: Icon(
                          Icons.shuffle,
                          color: isShuffled
                              ? Colors.deepPurpleAccent
                              : Colors.grey,
                        ),
                        label: const Text('Shuffle'),
                        onPressed: () => Audio.setShuffle(!isShuffled),
                      );
                    },
                  ),
                  StreamBuilder<double>(
                    stream: Audio.speedStream,
                    initialData: 1.0,
                    builder: (context, snapshot) {
                      final speed = snapshot.data ?? 1.0;
                      return OutlinedButton.icon(
                        icon: Icon(
                          Icons.speed,
                          color: speed == 1.0
                              ? Colors.grey
                              : Colors.deepPurpleAccent,
                        ),
                        label: Text('${speed}x'),
                        onPressed: () {
                          final nextSpeed = speed == 1.0
                              ? 1.5
                              : speed == 1.5
                              ? 2.0
                              : speed == 2.0
                              ? 0.5
                              : 1.0;
                          Audio.setSpeed(nextSpeed);
                        },
                      );
                    },
                  ),
                ],
              ),

              const SizedBox(height: 24),
              Text(
                'Playlist Queue',
                style: Theme.of(
                  context,
                ).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 8),

              // 3. Playlist UI
              Expanded(
                child: ListView.builder(
                  itemCount: _playlist.length,
                  itemBuilder: (context, i) {
                    final item = _playlist[i];
                    return ListTile(
                      contentPadding: EdgeInsets.zero,
                      leading: Container(
                        width: 48,
                        height: 48,
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(8),
                          image: DecorationImage(
                            image: NetworkImage(item.image ?? ''),
                            fit: BoxFit.cover,
                          ),
                        ),
                      ),
                      title: Text(item.title ?? 'Unknown'),
                      subtitle: Text(item.artist ?? 'Unknown Artist'),
                      trailing: const Icon(Icons.play_circle_outline),
                      onTap: () {
                        // Play specifically this track by loading a subset
                        // Or simple playback
                        Audio.play(
                          item.url,
                          title: item.title,
                          artist: item.artist,
                          image: item.image,
                        );
                      },
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
2
likes
130
points
150
downloads

Documentation

API reference

Publisher

verified publisherwebcode.codes

Weekly Downloads

A professional, zero-config audio playback library for Flutter. Supports playlists, background playback, lock screen controls, and robust error handling out-of-the-box.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

audio_service, audio_session, equatable, flutter, just_audio

More

Packages that depend on simple_audio_kit