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

需要装依赖:

  gallery_saver: ^2.3.2
  video_player: ^2.8.3

实现代码

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();
  }
}

最近更新

  1. TCP协议是安全的吗?

    2024-03-22 05:24:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-22 05:24:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-22 05:24:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-22 05:24:01       18 阅读

热门阅读

  1. ollama -linux部署

    2024-03-22 05:24:01       21 阅读
  2. Linux 常用命令 chgrp

    2024-03-22 05:24:01       21 阅读
  3. MyBatis面试简答题

    2024-03-22 05:24:01       18 阅读
  4. 使用Linq的Distinct方法

    2024-03-22 05:24:01       18 阅读
  5. Linux:协议定制以及序列化和反序列化

    2024-03-22 05:24:01       17 阅读
  6. C语言学习笔记day11

    2024-03-22 05:24:01       19 阅读
  7. 网络编程模拟面试题总结, sqlite3的c语言调用,

    2024-03-22 05:24:01       19 阅读
  8. hive语法树分析,判断 sql语句中有没有select *

    2024-03-22 05:24:01       21 阅读