zeba_academy_offline_media_player 1.0.0
zeba_academy_offline_media_player: ^1.0.0 copied to clipboard
Offline audio & video player with playlist, subtitles, shuffle/repeat, and speed control.
example/lib/main.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:zeba_academy_offline_media_player/zeba_academy_offline_media_player.dart';
import 'package:chewie/chewie.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Offline Media Player Example',
theme: ThemeData.dark(useMaterial3: true),
home: const MediaPlayerScreen(),
debugShowCheckedModeBanner: false,
);
}
}
class MediaPlayerScreen extends StatefulWidget {
const MediaPlayerScreen({super.key});
@override
State<MediaPlayerScreen> createState() => _MediaPlayerScreenState();
}
class _MediaPlayerScreenState extends State<MediaPlayerScreen> {
late OfflineMediaPlayer _player;
@override
void initState() {
super.initState();
// Example local files (update paths to your machine)
final playlist = [
MediaItem(
filePath: "C:/Users/Sarvesh/Videos/sample_video.mp4",
isVideo: true,
subtitlePath: "C:/Users/Sarvesh/Videos/sample.srt",
),
MediaItem(
filePath: "C:/Users/Sarvesh/Music/sample_audio.mp3",
isVideo: false,
),
];
_player = OfflineMediaPlayer(playlist: playlist);
_player.play();
}
@override
void dispose() {
_player.dispose();
super.dispose();
}
Widget _buildVideoPlayer() {
if (_player.current.isVideo && _player.chewieController != null) {
return AspectRatio(
aspectRatio: _player.chewieController!.videoPlayerController.value.aspectRatio,
child: Chewie(controller: _player.chewieController!),
);
} else {
return const Icon(
Icons.audiotrack,
size: 150,
color: Colors.blueAccent,
);
}
}
Widget _buildControls() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: const Icon(Icons.skip_previous),
iconSize: 36,
onPressed: () => setState(() => _player.previous()),
),
IconButton(
icon: const Icon(Icons.pause),
iconSize: 36,
onPressed: () => setState(() => _player.pause()),
),
IconButton(
icon: const Icon(Icons.play_arrow),
iconSize: 36,
onPressed: () => setState(() => _player.play()),
),
IconButton(
icon: const Icon(Icons.skip_next),
iconSize: 36,
onPressed: () => setState(() => _player.next()),
),
],
);
}
Widget _buildSettings() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => setState(() => _player.shuffle = !_player.shuffle),
child: Text(_player.shuffle ? "Shuffle ON" : "Shuffle OFF"),
),
const SizedBox(width: 12),
ElevatedButton(
onPressed: () {
setState(() {
_player.repeatMode = _player.repeatMode == RepeatMode.off
? RepeatMode.all
: _player.repeatMode == RepeatMode.all
? RepeatMode.one
: RepeatMode.off;
});
},
child: Text("Repeat: ${_player.repeatMode.name.toUpperCase()}"),
),
],
);
}
@override
Widget build(BuildContext context) {
final currentFile = _player.current.filePath.split(Platform.pathSeparator).last;
return Scaffold(
appBar: AppBar(
title: const Text("Offline Media Player"),
centerTitle: true,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Expanded(child: Center(child: _buildVideoPlayer())),
const SizedBox(height: 16),
Text(
"Now Playing: $currentFile",
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500),
),
const SizedBox(height: 16),
_buildControls(),
const SizedBox(height: 16),
_buildSettings(),
const SizedBox(height: 16),
],
),
),
);
}
}