multimedia_player 0.1.0 copy "multimedia_player: ^0.1.0" to clipboard
multimedia_player: ^0.1.0 copied to clipboard

A production-grade, cross-platform Flutter video player package supporting network URLs, local files, assets, RTSP, HLS, DASH with customizable controls and memory-efficient playback.

example/lib/main.dart

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

void main() {
  runApp(const MultimediaPlayerExampleApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Multimedia Player Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const ExampleHomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Multimedia Player Examples'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _buildExampleCard(
            context,
            title: 'Basic Network Video',
            description:
                'Play a video from a network URL with default controls',
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (_) => const BasicNetworkVideoExample(),
              ),
            ),
          ),
          _buildExampleCard(
            context,
            title: 'Custom Controls',
            description: 'Video player with custom control UI',
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (_) => const CustomControlsExample()),
            ),
          ),
          _buildExampleCard(
            context,
            title: 'Video List',
            description: 'Multiple videos in a scrollable list with auto-pause',
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (_) => const VideoListExample()),
            ),
          ),
          _buildExampleCard(
            context,
            title: 'HLS Stream',
            description: 'Play HLS (.m3u8) adaptive streaming video',
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (_) => const HlsStreamExample()),
            ),
          ),
          _buildExampleCard(
            context,
            title: 'Advanced Features',
            description: 'Playback speed, volume control, and more',
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (_) => const AdvancedFeaturesExample(),
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildExampleCard(
    BuildContext context, {
    required String title,
    required String description,
    required VoidCallback onTap,
  }) {
    return Card(
      margin: const EdgeInsets.only(bottom: 16),
      child: ListTile(
        title: Text(
          title,
          style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
        ),
        subtitle: Padding(
          padding: const EdgeInsets.only(top: 8),
          child: Text(description),
        ),
        trailing: const Icon(Icons.arrow_forward_ios),
        onTap: onTap,
      ),
    );
  }
}

// Basic Network Video Example
class BasicNetworkVideoExample extends StatefulWidget {
  const BasicNetworkVideoExample({super.key});

  @override
  State<BasicNetworkVideoExample> createState() =>
      _BasicNetworkVideoExampleState();
}

class _BasicNetworkVideoExampleState extends State<BasicNetworkVideoExample> {
  late MultimediaVideoController _controller;

  @override
  void initState() {
    super.initState();
    // Sample video URL (Big Buck Bunny)
    _controller = MultimediaVideoController(
      source: VideoSource.network(
        'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
      ),
      config: const VideoPlayerConfig(autoPlay: true, looping: true),
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Basic Network Video')),
      body: Center(
        child: AspectRatio(
          aspectRatio: 16 / 9,
          child: MultimediaVideoPlayer(controller: _controller),
        ),
      ),
    );
  }
}

// Custom Controls Example
class CustomControlsExample extends StatefulWidget {
  const CustomControlsExample({super.key});

  @override
  State<CustomControlsExample> createState() => _CustomControlsExampleState();
}

class _CustomControlsExampleState extends State<CustomControlsExample> {
  late MultimediaVideoController _controller;

  @override
  void initState() {
    super.initState();
    _controller = MultimediaVideoController(
      source: VideoSource.network(
        'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4',
      ),
      config: const VideoPlayerConfig(autoPlay: false),
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Custom Controls')),
      body: Column(
        children: [
          Expanded(
            child: MultimediaVideoPlayer(
              controller: _controller,
              controlsBuilder: (controller) => _buildCustomControls(controller),
            ),
          ),
          _buildExternalControls(),
        ],
      ),
    );
  }

  Widget _buildCustomControls(MultimediaVideoController controller) {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topCenter,
          end: Alignment.bottomCenter,
          colors: [Colors.transparent, Colors.black.withValues(alpha: 0.7)],
        ),
      ),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          AnimatedBuilder(
            animation: controller,
            builder: (context, child) {
              return Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  IconButton(
                    icon: const Icon(Icons.replay_10, color: Colors.white),
                    onPressed: () => controller.seekBackward(),
                  ),
                  IconButton(
                    icon: Icon(
                      controller.isPlaying ? Icons.pause : Icons.play_arrow,
                      color: Colors.white,
                      size: 48,
                    ),
                    onPressed: () => controller.togglePlayPause(),
                  ),
                  IconButton(
                    icon: const Icon(Icons.forward_10, color: Colors.white),
                    onPressed: () => controller.seekForward(),
                  ),
                ],
              );
            },
          ),
        ],
      ),
    );
  }

  Widget _buildExternalControls() {
    return Container(
      padding: const EdgeInsets.all(16),
      color: Colors.grey[200],
      child: Column(
        children: [
          const Text(
            'External Controls',
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 16),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton.icon(
                onPressed: () => _controller.play(),
                icon: const Icon(Icons.play_arrow),
                label: const Text('Play'),
              ),
              ElevatedButton.icon(
                onPressed: () => _controller.pause(),
                icon: const Icon(Icons.pause),
                label: const Text('Pause'),
              ),
              ElevatedButton.icon(
                onPressed: () => _controller.seekTo(Duration.zero),
                icon: const Icon(Icons.replay),
                label: const Text('Restart'),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

// Video List Example
class VideoListExample extends StatelessWidget {
  const VideoListExample({super.key});

  static final List<String> _videoUrls = [
    'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
    'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4',
    'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4',
    'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Video List')),
      body: ListView.builder(
        itemCount: _videoUrls.length,
        itemBuilder: (context, index) {
          return VideoListItem(videoUrl: _videoUrls[index], index: index);
        },
      ),
    );
  }
}

class VideoListItem extends StatefulWidget {
  final String videoUrl;
  final int index;

  const VideoListItem({super.key, required this.videoUrl, required this.index});

  @override
  State<VideoListItem> createState() => _VideoListItemState();
}

class _VideoListItemState extends State<VideoListItem> {
  late MultimediaVideoController _controller;

  @override
  void initState() {
    super.initState();
    _controller = MultimediaVideoController(
      source: VideoSource.network(widget.videoUrl),
      config: VideoPlayerConfig.forList(
        autoPlay: false,
        pauseOnInvisible: true,
      ),
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            'Video ${widget.index + 1}',
            style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 8),
          AspectRatio(
            aspectRatio: 16 / 9,
            child: MultimediaVideoPlayer(
              controller: _controller,
              enableVisibilityTracking: true,
              visibilityKey: ValueKey('video_${widget.index}'),
            ),
          ),
        ],
      ),
    );
  }
}

// HLS Stream Example
class HlsStreamExample extends StatefulWidget {
  const HlsStreamExample({super.key});

  @override
  State<HlsStreamExample> createState() => _HlsStreamExampleState();
}

class _HlsStreamExampleState extends State<HlsStreamExample> {
  late MultimediaVideoController _controller;

  @override
  void initState() {
    super.initState();
    // Sample HLS stream
    _controller = MultimediaVideoController(
      source: VideoSource.hls(
        'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8',
      ),
      config: const VideoPlayerConfig(
        autoPlay: true,
        showBufferingIndicator: true,
      ),
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('HLS Stream')),
      body: Column(
        children: [
          Expanded(child: MultimediaVideoPlayer(controller: _controller)),
          Container(
            padding: const EdgeInsets.all(16),
            color: Colors.grey[200],
            child: const Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'HLS Adaptive Streaming',
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
                ),
                SizedBox(height: 8),
                Text(
                  'This video uses HTTP Live Streaming (HLS) which automatically '
                  'adjusts quality based on network conditions.',
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

// Advanced Features Example
class AdvancedFeaturesExample extends StatefulWidget {
  const AdvancedFeaturesExample({super.key});

  @override
  State<AdvancedFeaturesExample> createState() =>
      _AdvancedFeaturesExampleState();
}

class _AdvancedFeaturesExampleState extends State<AdvancedFeaturesExample> {
  late MultimediaVideoController _controller;
  String _statusText = 'Initializing...';

  @override
  void initState() {
    super.initState();
    _controller = MultimediaVideoController(
      source: VideoSource.network(
        'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
      ),
      config: const VideoPlayerConfig(
        autoPlay: false,
        showPlaybackSpeed: true,
        showVolumeControl: true,
      ),
    );

    // Setup event listeners
    _controller.onPlay(() {
      setState(() => _statusText = 'Playing');
    });

    _controller.onPause(() {
      setState(() => _statusText = 'Paused');
    });

    _controller.onBuffering(() {
      setState(() => _statusText = 'Buffering...');
    });

    _controller.onCompleted(() {
      setState(() => _statusText = 'Completed');
    });

    _controller.onError((error) {
      setState(() => _statusText = 'Error: $error');
    });

    _controller.onPositionChanged((position) {
      // Position updates every 500ms
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Advanced Features')),
      body: Column(
        children: [
          Expanded(child: MultimediaVideoPlayer(controller: _controller)),
          Container(
            padding: const EdgeInsets.all(16),
            color: Colors.grey[200],
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Status: $_statusText',
                  style: const TextStyle(fontWeight: FontWeight.bold),
                ),
                const SizedBox(height: 16),
                AnimatedBuilder(
                  animation: _controller,
                  builder: (context, child) {
                    final state = _controller.state;
                    return Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          'Position: ${FormatHelper.formatDuration(state.position)}',
                        ),
                        Text(
                          'Duration: ${FormatHelper.formatDuration(state.duration)}',
                        ),
                        Text('Speed: ${state.playbackSpeed}x'),
                        Text('Volume: ${(state.volume * 100).toInt()}%'),
                        Text(
                          'Buffered: ${FormatHelper.formatPercentage(state.bufferPercentage)}',
                        ),
                      ],
                    );
                  },
                ),
                const SizedBox(height: 16),
                Wrap(
                  spacing: 8,
                  children: [
                    ElevatedButton(
                      onPressed: () => _controller.setPlaybackSpeed(0.5),
                      child: const Text('0.5x'),
                    ),
                    ElevatedButton(
                      onPressed: () => _controller.setPlaybackSpeed(1.0),
                      child: const Text('1.0x'),
                    ),
                    ElevatedButton(
                      onPressed: () => _controller.setPlaybackSpeed(1.5),
                      child: const Text('1.5x'),
                    ),
                    ElevatedButton(
                      onPressed: () => _controller.setPlaybackSpeed(2.0),
                      child: const Text('2.0x'),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
0
likes
150
points
15
downloads

Publisher

verified publishersyedbipul.me

Weekly Downloads

A production-grade, cross-platform Flutter video player package supporting network URLs, local files, assets, RTSP, HLS, DASH with customizable controls and memory-efficient playback.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, http, video_player, video_player_web, visibility_detector

More

Packages that depend on multimedia_player