flutter实现视频播放器,可根据指定视频地址播放、设置声音,进度条拖动,下载等

需要装依赖:

java 复制代码
  gallery_saver: ^2.3.2
  video_player: ^2.8.3

AndroidManifest.xml

java 复制代码
<uses-permission android:name="android.permission.INTERNET"/>

实现代码

java 复制代码
import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:gallery_saver/gallery_saver.dart';
import 'package:path_provider/path_provider.dart';
import 'package:video_player/video_player.dart';
import 'package:http/http.dart' as http;

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

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

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

class _VideoAppState extends State<VideoApp> {
  late VideoPlayerController _controller;
  bool isMuted = false;
  double _currentSliderValue = 0.0;
  Timer? _timer;
  double _playbackSpeed = 1.0;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.networkUrl(Uri.parse(
        '你的播放地址'
    ))
      ..initialize().then((_) {
        setState(() {});
      });
    _controller.setLooping(true);
    _controller.play();

    _timer = Timer.periodic(Duration(seconds: 1), (Timer timer) {
      if (_controller.value.isPlaying) {
        setState(() {
          _currentSliderValue = _controller.value.position.inMilliseconds.toDouble();
        });
      }
    });
  }

  Future<void> downloadAndSaveVideo(String url) async {
    var httpClient = http.Client();
    var response = await httpClient.get(Uri.parse(url));
    var bytes = response.bodyBytes;
    var tempDir = await getTemporaryDirectory();
    var tempFile = File('${tempDir.path}/temp_video.mp4');
    await tempFile.writeAsBytes(bytes);

    final result = await GallerySaver.saveVideo(tempFile.path);
    print('Video saved to gallery: $result,path: ${tempFile.path}');
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Video Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Video Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              _controller.value.isInitialized
                  ? AspectRatio(
                aspectRatio: _controller.value.aspectRatio,
                child: VideoPlayer(_controller),
              )
                  :const  CircularProgressIndicator(),
              const SizedBox(height: 5),
              ElevatedButton(
                onPressed: () {
                  setState(() {
                    isMuted = !isMuted;
                    _controller.setVolume(isMuted ? 0.0 : 1.0);
                  });
                },
                child: Text(isMuted ? '静音模式' : '开启声音模式'),
              ),
              ElevatedButton(
                onPressed: () {
                  setState(() {
                    if (_controller.value.isPlaying) {
                      _controller.pause();
                    } else {
                      _controller.play();
                    }
                  });
                },
                child: Text(_controller.value.isPlaying ? '暂停' : '播放'),
              ),
              Slider(
                value: _currentSliderValue,
                min: 0.0,
                max: _controller.value.duration.inMilliseconds.toDouble(),
                onChanged: (double value) {
                  setState(() {
                    _currentSliderValue = value;
                    _controller.seekTo(Duration(milliseconds: value.toInt()));
                  });
                },
              ),
              const SizedBox(height: 5),
              Text('Playback Speed: ${_playbackSpeed.toStringAsFixed(1)}x'),
              Slider(
                value: _playbackSpeed,
                min: 0.5,
                max: 2.0,
                divisions: 15,
                label: '${_playbackSpeed.toStringAsFixed(1)}x',
                onChanged: (double value) {
                  setState(() {
                    _playbackSpeed = value;
                    _controller.setPlaybackSpeed(_playbackSpeed);
                  });
                },
              ),
              ElevatedButton(
                onPressed: () {
                  downloadAndSaveVideo(_controller.dataSource);
                },
                child: Text('下载'),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
    _timer?.cancel();
  }
}
相关推荐
●VON7 小时前
Flutter 鸿蒙插件适配实战:用 clipboard_watcher 0.3.0 监听剪贴板变化
flutter·华为·harmonyos
天空之城--9 小时前
Flutter Drift 完全指南:从原理到实战
jvm·flutter·oracle
yume_sibai13 小时前
02-Flutter进阶开发
前端·flutter
●VON15 小时前
Flutter 鸿蒙插件适配实战:用 is_lock_screen 2.0.0 判断真实锁屏状态
flutter·华为·harmonyos
●VON17 小时前
Flutter 鸿蒙插件适配实战:用 flutter_timezone_observer 1.2.0 监听系统时区变化
flutter·华为·harmonyos
●VON17 小时前
Flutter 鸿蒙 app_install_date 0.1.5 使用实战:读取应用安装时间
flutter·华为·harmonyos
●VON19 小时前
Flutter 鸿蒙插件适配实战:flutter_screenshot_detect 0.1.7 截图事件监听
flutter·华为·harmonyos·鸿蒙
西西学代码1 天前
尾灯-应用层通信协议(BLE)
flutter
恋猫de小郭2 天前
iPhone Duo 适配详解,需要改变的不止是布局模型
前端·flutter·ios