A nostalgic Flutter app that recreates the classic cassette tape player experience with realistic animations and audio playback. Now available as a reusable widget for your Flutter projects!
The cassette player is now a fully reusable widget that you can easily integrate into any Flutter project!
-
Copy these files to your project:
lib/ ├── cassette_player.dart # Main widget ├── tape_painter.dart # Cassette graphics └── tape_button.dart # Control buttons -
Add dependency to your
pubspec.yaml:dependencies: audioplayers: ^6.1.0
-
Use the widget in your app:
import 'package:your_app/cassette_player.dart'; CassettePlayer( playlist: [ AudioTrack( id: '1', title: 'My Song', artist: 'Artist Name', source: AssetSource('audio/song.mp3'), ), ], autoPlay: true, )
CassettePlayer(
playlist: myPlaylist,
config: CassettePlayerConfig(
backgroundColor: Colors.purple,
width: 350,
height: 230,
timeTextStyle: TextStyle(color: Colors.white),
),
onTrackChanged: (track) {
print('Now playing: ${track?.displayTitle}');
},
onError: (error) {
showSnackBar(error);
},
)- 🎼 Audio Playback: Play any audio format supported by audioplayers
- 📼 Realistic Cassette Animation: Watch the tape reels spin and transfer tape as the audio plays
- ⏱️ Time Display: Track current position and total duration in MM:SS format
- 🎨 Fully Customizable: Colors, sizes, fonts - make it match your app's theme
- 🎵 Playlist Support: Built-in playlist management with next/previous
- 📁 Multiple Audio Sources: Assets, URLs, or device files
- 🎮 External Control: Control playback programmatically via GlobalKey
- 📡 Event Callbacks: Listen to track changes, playback state, and progress
| Property | Type | Description |
|---|---|---|
playlist |
List<AudioTrack> |
List of tracks to play |
config |
CassettePlayerConfig |
Visual customization options |
autoPlay |
bool |
Start playing immediately |
initialTrackIndex |
int |
Which track to load first |
| Callback | Type | Description |
|---|---|---|
onTrackChanged |
Function(AudioTrack?) |
Called when track changes |
onPlaybackStateChanged |
Function(PlayerState) |
Called on play/pause/stop |
onProgressChanged |
Function(Duration, Duration?) |
Called during playback |
onError |
Function(String) |
Called on errors |
final playerKey = GlobalKey<CassettePlayerState>();
// Use the key
CassettePlayer(key: playerKey, ...)
// Control playback
playerKey.currentState?.play();
playerKey.currentState?.pause();
playerKey.currentState?.next();
playerKey.currentState?.seekTo(Duration(seconds: 30));lib/
├── main.dart # Example app entry point
├── home.dart # Example usage
├── cassette_player.dart # ⭐ Main reusable widget
├── tape_painter.dart # Custom painter for graphics
├── tape_button.dart # Button component
├── example_usage.dart # Multiple usage examples
└── CASSETTE_PLAYER_WIDGET.md # Widget documentation
assets/
└── audio/ # Audio files for demo
├── pl-PL-Chirp3-HD-Achernar.wav
└── pl-PL-Chirp3-HD-Enceladus.wav
- Flutter SDK: ^3.7.2
- Dart SDK: ^3.7.2
- iOS 12.1+ / Android API 21+
- Clone the repository:
git clone https://github.com/yourusername/retroPlayer.git
cd retroPlayer- Install dependencies:
flutter pub get- Run the app:
flutter runCassettePlayer(
playlist: [
AudioTrack(
id: '1',
title: 'Song Name',
source: AssetSource('audio/song.mp3'),
),
],
)CassettePlayer(
playlist: [
AudioTrack(
id: '1',
title: 'Online Radio',
source: UrlSource('https://stream.example.com/radio.mp3'),
),
],
)CassettePlayer(
playlist: myTracks,
config: CassettePlayerConfig(
backgroundColor: Colors.black,
cassetteColor: Color(0xff1a1a1a),
labelColor: Colors.purple,
width: 280,
height: 180,
),
)CassettePlayer(
playlist: myTracks,
onTrackChanged: (track) => updateUI(track),
onPlaybackStateChanged: (state) => handleState(state),
onProgressChanged: (pos, total) => updateSlider(pos, total),
onError: (error) => showError(error),
)- 📖 Widget API Documentation - Detailed widget documentation
- 🤖 Development Notes - Technical notes for AI assistants
- 📝 Example Usage - Complete code examples
- Increase volume: Device → Increase Volume (Cmd+Up)
- Check Mac system volume
- Test on a real device for best results
- Ensure audio files are in
assets/audio/directory - Run
flutter clean && flutter pub getafter adding new assets - Check that
pubspec.yamlincludes the assets section
- Make sure all three files are copied (cassette_player, tape_painter, tape_button)
- Check that audioplayers dependency is added
- Verify import paths are correct
Feel free to submit issues and enhancement requests!
This project is open source and available under the MIT License.
Made with ❤️ for the nostalgic souls who miss the analog days
