需要装依赖:
gallery_saver: ^2.3.2
video_player: ^2.8.3
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
实现代码
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();
}
}