Flutter视频处理插件ffmpeg_cli的使用

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

Flutter视频处理插件ffmpeg_cli的使用

什么是FFMPEG?

FFMPEG 是一个非常受欢迎且历史悠久的工具,用于读取、写入和流式传输音频和视频内容。大多数开发人员通过其命令行界面(CLI)使用 FFMPEG,因为这比直接与构建 FFMPEG 的 C 代码交互要容易得多。

什么是 ffmpeg_cli

这个包允许你用 Dart 代码配置 FFMPEG CLI 命令。 ffmpeg_cli 故意保留了 FFMPEG 命令的复杂性,以确保 FFMPEG CLI 能做的任何事情,ffmpeg_cli 包都可以做到。

快速开始

首先,确保你的设备上安装了 ffmpeg,并且它可以在你的系统路径中访问。

示例:合并多个视频文件

以下是一个简单的例子,展示如何使用 ffmpeg_cli 合并多个视频文件。

import 'package:ffmpeg_cli/ffmpeg_cli.dart';

void main() async {
  // 定义输出流,它将映射到视频文件。ID 名称可以是任何你喜欢的名字。
  const outputStream = FfmpegStream(
    videoId: "[final_v]", 
    audioId: "[final_a]",
  );

  // 组合你想要的 FFMPEG 命令,包括输入、过滤器、参数和输出位置。
  final command = FfmpegCommand(
    inputs: [
      FfmpegInput.asset("assets/intro.mp4"),
      FfmpegInput.asset("assets/content.mp4"),
      FfmpegInput.asset("assets/outro.mov"),
    ],
    args: [
      // 映射过滤器图到视频文件输出。
      CliArg(name: 'map', value: outputStream.videoId!),
      CliArg(name: 'map', value: outputStream.audioId!),
      const CliArg(name: 'vsync', value: '2'),
    ],
    filterGraph: FilterGraph(
      chains: [
        FilterChain(
          inputs: [
            // 将所有3个视频资源发送到 concat 过滤器。
            const FfmpegStream(videoId: "[0:v]", audioId: "[0:a]"),
            const FfmpegStream(videoId: "[1:v]", audioId: "[1:a]"),
            const FfmpegStream(videoId: "[2:v]", audioId: "[2:a]"),
          ],
          filters: [
            // 拼接3个片段。
            ConcatFilter(
              segmentCount: 3, 
              outputVideoStreamCount: 1, 
              outputAudioStreamCount: 1,
            ),
          ],
          outputs: [
            // 给输出流分配给定的音频/视频 ID
            outputStream,
          ],
        ),
      ],
    ),
    outputFilepath: "/my/output/file.mp4",
  );

  // 执行命令
  final process = await Ffmpeg().run(command: command);
}

如何管理 ffprobe 支持

ffprobe 中有很多属性,其中许多属性可能以不同的格式呈现,并且这些格式没有很好地记录。 对于 ffprobe 的方法是随着发现添加缺失的结果参数,并根据发现的各种可能格式为每个属性添加解析功能。换句话说,在给定时刻只做必要的事情,因为整体范围太大且难以发现。

完整示例 Demo

为了更完整地理解 ffmpeg_cli 插件的使用,下面提供了一个完整的示例项目结构,包含必要的依赖项和一个简单的视频合并应用。

项目结构

lib/
├── main.dart
└── ffmpeg_service.dart
pubspec.yaml
assets/
├── intro.mp4
├── content.mp4
└── outro.mov

pubspec.yaml

确保在 pubspec.yaml 文件中添加 ffmpeg_cli 依赖项:

dependencies:
  flutter:
    sdk: flutter
  ffmpeg_cli: ^latest_version # 替换为最新版本号

ffmpeg_service.dart

创建一个服务类来封装 FFMPEG 操作:

import 'package:ffmpeg_cli/ffmpeg_cli.dart';
import 'dart:io';

class FFmpegService {
  Future<void> mergeVideos() async {
    try {
      const outputStream = FfmpegStream(
        videoId: "[final_v]", 
        audioId: "[final_a]",
      );

      final command = FfmpegCommand(
        inputs: [
          FfmpegInput.asset("assets/intro.mp4"),
          FfmpegInput.asset("assets/content.mp4"),
          FfmpegInput.asset("assets/outro.mov"),
        ],
        args: [
          CliArg(name: 'map', value: outputStream.videoId!),
          CliArg(name: 'map', value: outputStream.audioId!),
          const CliArg(name: 'vsync', value: '2'),
        ],
        filterGraph: FilterGraph(
          chains: [
            FilterChain(
              inputs: [
                const FfmpegStream(videoId: "[0:v]", audioId: "[0:a]"),
                const FfmpegStream(videoId: "[1:v]", audioId: "[1:a]"),
                const FfmpegStream(videoId: "[2:v]", audioId: "[2:a]"),
              ],
              filters: [
                ConcatFilter(
                  segmentCount: 3, 
                  outputVideoStreamCount: 1, 
                  outputAudioStreamCount: 1,
                ),
              ],
              outputs: [outputStream],
            ),
          ],
        ),
        outputFilepath: "${Directory.systemTemp.path}/merged_video.mp4",
      );

      final process = await Ffmpeg().run(command: command);

      if (process.exitCode == 0) {
        print("视频合并成功!");
      } else {
        print("视频合并失败,错误信息:${process.stderr}");
      }
    } catch (e) {
      print("发生错误:$e");
    }
  }
}

main.dart

在主应用程序中调用合并视频的服务:

import 'package:flutter/material.dart';
import 'ffmpeg_service.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('FFMPEG CLI Example')),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              FFmpegService().mergeVideos();
            },
            child: Text('合并视频'),
          ),
        ),
      ),
    );
  }
}

以上代码展示了如何在 Flutter 应用程序中使用 ffmpeg_cli 插件来处理视频文件。你可以根据需要修改和扩展此示例,以适应具体的应用场景。


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

1 回复

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


当然,关于在Flutter中使用ffmpeg_cli插件进行视频处理,以下是一个简单的代码示例,展示了如何使用该插件来执行一些基本的视频处理任务。

首先,确保你已经在pubspec.yaml文件中添加了ffmpeg_cli依赖:

dependencies:
  flutter:
    sdk: flutter
  ffmpeg_cli: ^0.4.0  # 请检查最新版本号

然后,运行flutter pub get来安装依赖。

接下来是一个使用ffmpeg_cli的示例代码,展示了如何裁剪视频:

import 'package:flutter/material.dart';
import 'package:ffmpeg_cli/ffmpeg_cli.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: VideoProcessingScreen(),
    );
  }
}

class VideoProcessingScreen extends StatefulWidget {
  @override
  _VideoProcessingScreenState createState() => _VideoProcessingScreenState();
}

class _VideoProcessingScreenState extends State<VideoProcessingScreen> {
  String result = "";

  Future<void> processVideo(String inputPath, String outputPath, String startTime, String duration) async {
    try {
      // 构建ffmpeg命令
      String command = '-i $inputPath -ss $startTime -t $duration -c copy $outputPath';
      
      // 执行ffmpeg命令
      await FFmpegCli().execute(command);
      
      setState(() {
        result = "视频处理成功!输出路径:$outputPath";
      });
    } catch (e) {
      setState(() {
        result = "视频处理失败:${e.message}";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('FFmpeg CLI 示例'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () async {
                // 输入视频路径
                String inputPath = "/path/to/input/video.mp4";
                // 输出视频路径
                String outputPath = "/path/to/output/video_clipped.mp4";
                // 开始时间(格式:HH:MM:SS 或 SS)
                String startTime = "00:00:30"; // 从第30秒开始
                // 持续时间(格式:HH:MM:SS 或 SS)
                String duration = "10"; // 持续10秒
                
                await processVideo(inputPath, outputPath, startTime, duration);
              },
              child: Text('裁剪视频'),
            ),
            Text(result),
          ],
        ),
      ),
    );
  }
}

注意事项:

  1. 路径问题:在实际使用中,你需要确保inputPathoutputPath是有效的文件路径。在Flutter应用中,特别是移动平台上,处理文件路径可能需要请求存储权限或使用特定的文件访问API。
  2. 命令格式ffmpeg命令的格式非常灵活,上述示例中的命令仅用于裁剪视频。你可以根据需要调整命令以实现其他功能,如转换格式、压缩视频等。
  3. 错误处理:在实际应用中,应添加更详细的错误处理逻辑,以处理可能的异常情况,如文件不存在、权限不足等。
  4. 性能考虑:视频处理是一个资源密集型任务,可能会影响应用的性能。在移动设备上执行长时间的视频处理时,应考虑使用后台服务或通知用户处理进度。

上述代码提供了一个基础框架,你可以根据具体需求进行扩展和修改。

回到顶部