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();
  }
}
相关推荐
许进进16 小时前
FlutterWeb渲染模式及提速
android·flutter·web
喵个咪18 小时前
Flutter 使用 RxDart & Streams 实现 BLoC模式
前端·flutter·reactivex
iFlyCai1 天前
Flutter本地数据持久化的几种方式
flutter
snwrking2 天前
各个版本Android上的Location与Notification权限的问题
android·flutter
头好晕呀2 天前
Flutter+WebRTC开发点对点加密即时通讯APP--好友列表界面实现
android·前端·flutter
coder_pig3 天前
跟🤡杰哥一起学Flutter (十九、Flutter混编杂谈[Android]😫)
android·flutter·harmonyos
鳄鱼不怕_牙医不怕4 天前
Flutter 源码梳理系列(十):BuildOwner class
flutter·源码阅读
甜瓜看代码4 天前
让你的切换丝滑起来,Hero animations的介绍
flutter
啊猪是的读来过倒4 天前
Vue 全局状态管理新宠:Pinia实战指南
前端·vue.js·flutter·pinia·全局状态管理
偷野的程咬金5 天前
了解flutter中SingleTickerProviderStateMixin的使用
flutter