Flutter视频编辑插件custom_video_editor的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter视频编辑插件custom_video_editor的使用

功能

  • 裁剪
  • 剪辑

自定义视频编辑器展示

自定义视频编辑器预览

如何使用此插件

为了开始编辑视频,请复制以下代码并根据需要进行修改。

Future<void> editVideo(String videoLink) async {
  final updatedRes = await Navigator.push(context, MaterialPageRoute(builder: (context) {
    return EditVideoComponent(videoLink: videoLink);
  }));
  if(updatedRes != null && updatedRes is FinishedVideoData){
    VideoPlayerController getController = VideoPlayerController.file(File(updatedRes.url));
    await getController.initialize();
    controller = getController;
    width = updatedRes.size.width;
    height = updatedRes.size.height;
  }
}

完整示例代码

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:video_player/video_player.dart';
import 'VideoEditor.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ImagePicker _picker = ImagePicker();
  List links = [];
  List components = [];
  List controllers = [];

  Future<void> pickVideo() async {
    try {
      if(true){
        final XFile? pickedFile = await _picker.pickVideo(
          source: ImageSource.gallery,
        );
        if(pickedFile != null ){
          String videoLUri = pickedFile.path;
          VideoPlayerController getController = VideoPlayerController.file(File(videoLUri));
          await getController.initialize();
          controllers.add(getController);
          links.add(pickedFile.path);
          components.add(
            Container(
              margin: EdgeInsets.symmetric(vertical: 20),
              width: getController.value.size.width, height: getController.value.size.height,
              child: VideoPlayer(getController)
            )
          );
          setState(() {});
        }
      }
    } catch (e) {
    }
  }

  Future<void> editVideo(String videoLink) async {
    final updatedRes = await Navigator.push(context, MaterialPageRoute(builder: (context) {
      return EditVideoComponent(videoLink: videoLink);
    }));
    if(updatedRes != null && updatedRes is FinishedVideoData){
      int index = links.indexOf(videoLink);
      controllers[index].dispose();
      components[index] = Container();
      links[index] = '';

      VideoPlayerController getController = VideoPlayerController.file(File(updatedRes.url));
      await getController.initialize();
      setState(() {
        links.insert(index, updatedRes.url);
        controllers.insert(index, getController);
        components.insert(
          index,
          Container(
            margin: EdgeInsets.symmetric(vertical: 20),
            width: updatedRes.size.width, height: updatedRes.size.height,
            child: VideoPlayer(getController)
          )
        );
      });
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: ListView(
          children: [
            ElevatedButton(
              onPressed: () => pickVideo(),
              child: Text('Pick Video')
            ),
            
            for(int i = 0; i < links.length; i++)
            Stack(
              children: [
                Positioned(
                  child: components[i]
                ),
                Positioned(
                  top: 15, right: 0.03 * getScreenWidth(),
                  child: Container(
                    width: 0.075 * getScreenWidth(),
                    height: 0.075 * getScreenWidth(),
                    decoration: BoxDecoration(
                      color: Colors.black,
                      shape: BoxShape.circle,
                    ),
                    child: GestureDetector(
                      onTap: (){
                        links[i] = '';
                        components[i] = Container();
                        controllers[i].dispose();
                        setState(() {});
                      },
                      child: Icon(Icons.delete, size: 25, color: Colors.white)
                    )
                  )
                ),
                Positioned(
                  top: 15, right: 0.13 * getScreenWidth(),
                  child: Container(
                    width: 0.075 * getScreenWidth(),
                    height: 0.075 * getScreenWidth(),
                    decoration: BoxDecoration(
                      color: Colors.black,
                      shape: BoxShape.circle,
                    ),
                    child: GestureDetector(
                      onTap: () => editVideo(links[i]),
                      child: Icon(Icons.edit, size: 25, color: Colors.white)
                    )
                  )
                ),
              ],
            )
          ],
        ),
      )
    );
  }
}

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

1 回复

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


当然,下面是一个关于如何使用 custom_video_editor 插件进行视频编辑的示例代码。custom_video_editor 是一个用于 Flutter 的视频编辑插件,支持裁剪、合并、添加水印等功能。在使用之前,请确保你已经在 pubspec.yaml 文件中添加了该插件的依赖。

dependencies:
  flutter:
    sdk: flutter
  custom_video_editor: ^最新版本号  # 请替换为最新版本号

示例代码

import 'package:flutter/material.dart';
import 'package:custom_video_editor/custom_video_editor.dart';
import 'package:path_provider/path_provider.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Video Editor Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: VideoEditorScreen(),
    );
  }
}

class VideoEditorScreen extends StatefulWidget {
  @override
  _VideoEditorScreenState createState() => _VideoEditorScreenState();
}

class _VideoEditorScreenState extends State<VideoEditorScreen> {
  late VideoEditorController _controller;
  late String _videoPath;

  @override
  void initState() {
    super.initState();
    _initVideoEditor();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  Future<void> _initVideoEditor() async {
    final directory = await getApplicationDocumentsDirectory();
    _videoPath = directory.path + '/sample_video.mp4';  // 请替换为你的视频路径

    _controller = VideoEditorController(
      videoPath: _videoPath,
    );

    // 监听编辑完成事件
    _controller.editCompleted.listen((outputPath) {
      print('Edited video saved at: $outputPath');
      // 可以在这里进行后续操作,比如显示保存成功的提示或者打开编辑后的视频
    });
  }

  Future<void> _trimVideo() async {
    // 裁剪视频,从第5秒到第10秒
    await _controller.trim(startTime: 5.0, endTime: 10.0);
  }

  Future<void> _addWatermark() async {
    // 添加水印,这里假设水印图片位于应用文档目录
    final directory = await getApplicationDocumentsDirectory();
    final watermarkPath = directory.path + '/watermark.png';  // 请替换为你的水印图片路径

    await _controller.addWatermark(
      watermarkPath: watermarkPath,
      position: WatermarkPosition(0.1, 0.1),  // 水印位置(相对于视频尺寸的百分比)
      size: WatermarkSize(0.2, 0.2),  // 水印大小(相对于视频尺寸的百分比)
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Video Editor Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () async {
                await _trimVideo();
              },
              child: Text('Trim Video'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                await _addWatermark();
              },
              child: Text('Add Watermark'),
            ),
          ],
        ),
      ),
    );
  }
}

注意事项

  1. 视频和水印路径:示例中的视频路径和水印图片路径需要根据你的实际情况进行替换。
  2. 权限:在实际应用中,你可能需要请求存储权限来访问视频文件和水印图片。
  3. 错误处理:为了代码的健壮性,你应该添加适当的错误处理逻辑,比如处理文件不存在的异常。

这个示例展示了如何使用 custom_video_editor 插件进行视频裁剪和添加水印的基本操作。根据插件的文档,你还可以探索更多高级功能,比如合并视频、调整视频速度等。

回到顶部