Flutter视频裁剪插件flutter_video_cut的使用

Flutter视频裁剪插件flutter_video_cut的使用

在本教程中,我们将展示如何使用flutter_video_cut插件来裁剪视频。我们将通过一个完整的示例代码来演示该插件的使用方法。

视频操作控制

Getting Started

首先,确保你已经在项目中添加了flutter_video_cut依赖项。打开pubspec.yaml文件并添加以下依赖:

dependencies:
  flutter_video_cut: ^x.x.x  # 请替换为最新版本号

然后运行flutter pub get以安装依赖项。

接下来,我们来看一个完整的示例代码,它展示了如何使用flutter_video_cut插件进行视频裁剪。

示例代码

文件结构

example/
├── lib/
│   └── main.dart

main.dart

import 'dart:io';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter_video_cut/flutter_video_cut.dart';
import 'package:video_player/video_player.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';

void main() {
  runApp(MaterialApp(home: VideoPage(),));
}

class VideoPage extends StatefulWidget {
  [@override](/user/override)
  _VideoPageState createState() => _VideoPageState();
}

class _VideoPageState extends State<VideoPage> {

  String? _oldVideoPath;

  VideoPlayerController? _playerController;

  StateSetter? _setter;

  String? _imgPath;

  late FFVideoCutModel cutModel = FFVideoCutModel();

  late ValueNotifier<int> _progress;

  [@override](/user/override)
  void initState() {
    // 初始化状态
    super.initState();
    _setupState();
  }

  // 初始化状态
  void _setupState() {
    _setter = setState;
    _progress = ValueNotifier(0);
    _test();
  }

  // 设置播放器控制器
  _setupPlayer(String path) {
    _playerController = VideoPlayerController.file(File(path))..initialize().then((value) {
      _setter!.call(() {});
      _playerController!.play();
    });
  }

  // 测试方法
  _test() async {
    var url = 'http://video.training.luojigou.vip/lh_bppTr94lBozn2tpboSZ_mSL-m_low.mp4';
    /*保存到缓存文件*/
    var fileInfo = await DefaultCacheManager().downloadFile(url);
    print('fileInfo===${fileInfo.file.path}');
    
    _oldVideoPath = fileInfo.file.path;

    _setupPlayer(_oldVideoPath!);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return  Scaffold(
      appBar: AppBar(title: Text('视频操作'),),
      body: Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        child: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              _buildVideoWidget(),
              SizedBox(height: 30,),
              _imgPath == null ? SizedBox() : Container(
                height: 200,
                width: double.infinity,
                child: Image.file(File(_imgPath!), fit: BoxFit.cover,),
              ),
              TextButton(onPressed: _onTapOldPath, child: Text('切换原视频')),
              TextButton(onPressed: _onTapCutPath, child: Text('剪切原视频')),
              TextButton(onPressed: _onTapCoverImg, child: Text('获取封面图')),
              // TextButton(onPressed: _onTapCompressSVGPath, child: Text('压缩分辨率原视频')),
              // TextButton(onPressed: _onTapCompressBitPath, child: Text('压缩码率原视频')),
            ],
          ),
        ),
      ),
    );
  }

  // 构建视频播放组件
  _buildVideoWidget() {
    if (_playerController == null) {
      return SizedBox(height: 300,);
    }
    return Container(
      // color: Colors.green,
        constraints: BoxConstraints(
          maxWidth: MediaQuery.of(context).size.width,
          maxHeight: 300,
        ),
        child: Stack(
          children: [
            _playerController!.value.isInitialized ? AspectRatio(aspectRatio: _playerController!.value.aspectRatio, child: VideoPlayer(_playerController!),) : Container(
              height: 300,
              width: double.infinity,
              child: Center(
                child: SizedBox(),
              ),
            ),
            ValueListenableBuilder<int>(valueListenable: _progress, builder: (ctx, value, child) {
              if (value == 0 || value >= 99) {
                return SizedBox();
              }
              return Container(
                color: Colors.black.withOpacity(0.3),
                width: double.infinity,
                height: double.infinity,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    SizedBox(
                      height: 50,
                      width: 50,
                      child: CircularProgressIndicator(),
                    ),
                    SizedBox(height: 5,),
                    Text('进度${_progress.value}%', style: TextStyle(color: Colors.white),)
                  ],
                ),
              );
            }),
          ],
        )
    );
  }

  // 切换原视频
  _onTapOldPath() {
    _setupPlayer(_oldVideoPath!);
  }

  // 剪切原视频
  _onTapCutPath() async {
    var startValue = 0.0;
    var endValue   = 20.0;
    _playerController!.pause();
    /*进度*/
    FFVideoUtil.getVideoCompressProgress((progress) {
      print('progress:$progress');
      _progress.value = int.parse(progress);
    }, endValue - startValue);

    cutModel = await FFVideoUtil.compressVideo(_oldVideoPath!, startValue: startValue, endValue: endValue);
    _setupPlayer(cutModel.path!);
  }

  // 获取封面图
  _onTapCoverImg() async {
    _imgPath = await FFVideoUtil.getVideoCoverImage(cutModel.path!);
    print('_imgPath===$_imgPath');
    setState(() {});
  }
}

更多关于Flutter视频裁剪插件flutter_video_cut的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter视频裁剪插件flutter_video_cut的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


flutter_video_cut 是一个用于在 Flutter 应用中裁剪视频的插件。它允许你选择视频文件的一部分并将其裁剪为新的视频文件。以下是使用 flutter_video_cut 插件的基本步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 flutter_video_cut 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_video_cut: ^0.1.0  # 请检查最新版本

然后,运行 flutter pub get 以获取依赖。

2. 导入插件

在你的 Dart 文件中导入 flutter_video_cut 插件:

import 'package:flutter_video_cut/flutter_video_cut.dart';

3. 初始化插件

在使用插件之前,你需要初始化它:

final videoCut = FlutterVideoCut();

4. 选择视频文件

你可以使用 ImagePicker 或其他方式来选择视频文件。例如,使用 ImagePicker 选择一个视频文件:

import 'package:image_picker/image_picker.dart';

final picker = ImagePicker();
final pickedFile = await picker.getVideo(source: ImageSource.gallery);

if (pickedFile != null) {
  final videoPath = pickedFile.path;
  // 使用 videoPath 进行裁剪
}

5. 裁剪视频

使用 flutter_video_cut 插件裁剪视频。你可以指定开始时间和结束时间:

final outputPath = "/path/to/output/video.mp4"; // 指定输出文件路径
final start = Duration(seconds: 10); // 开始时间
final end = Duration(seconds: 20); // 结束时间

final result = await videoCut.cutVideo(
  inputPath: videoPath,
  outputPath: outputPath,
  start: start,
  end: end,
);

if (result) {
  print("视频裁剪成功!");
} else {
  print("视频裁剪失败!");
}

6. 处理裁剪结果

裁剪操作完成后,你可以根据 result 值来处理成功或失败的情况。如果裁剪成功,你可以使用 outputPath 来播放或进一步处理裁剪后的视频。

7. 权限处理

确保在你的应用中正确处理文件和存储权限,尤其是在 Android 和 iOS 设备上。你可能需要在 AndroidManifest.xmlInfo.plist 中添加相应的权限声明。

8. 其他功能

flutter_video_cut 插件可能还提供其他功能,例如调整视频的分辨率、帧率等。请参考插件的文档以获取更多详细信息。

示例代码

以下是一个简单的示例代码,展示了如何使用 flutter_video_cut 插件裁剪视频:

import 'package:flutter/material.dart';
import 'package:flutter_video_cut/flutter_video_cut.dart';
import 'package:image_picker/image_picker.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: VideoCutExample(),
    );
  }
}

class VideoCutExample extends StatefulWidget {
  [@override](/user/override)
  _VideoCutExampleState createState() => _VideoCutExampleState();
}

class _VideoCutExampleState extends State<VideoCutExample> {
  final videoCut = FlutterVideoCut();
  String _videoPath;
  String _outputPath = "/path/to/output/video.mp4";

  Future<void> _pickVideo() async {
    final picker = ImagePicker();
    final pickedFile = await picker.getVideo(source: ImageSource.gallery);

    if (pickedFile != null) {
      setState(() {
        _videoPath = pickedFile.path;
      });
    }
  }

  Future<void> _cutVideo() async {
    if (_videoPath == null) return;

    final start = Duration(seconds: 10);
    final end = Duration(seconds: 20);

    final result = await videoCut.cutVideo(
      inputPath: _videoPath,
      outputPath: _outputPath,
      start: start,
      end: end,
    );

    if (result) {
      print("视频裁剪成功!");
    } else {
      print("视频裁剪失败!");
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('视频裁剪示例'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _videoPath != null
                ? Text("视频文件: $_videoPath")
                : Text("未选择视频文件"),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _pickVideo,
              child: Text("选择视频"),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _cutVideo,
              child: Text("裁剪视频"),
            ),
          ],
        ),
      ),
    );
  }
}
回到顶部