我的编程空间,编程开发者的网络收藏夹
学习永远不晚

【FFmpeg实战】Flutter音视频裁剪

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

【FFmpeg实战】Flutter音视频裁剪

作者:JianLee 链接:https://www.jianshu.com/p/868c8536a9b2

flutter_ffmpeg是什么?

ffmpeg是一个音视频处理库,通过命令行的形式,对音视频进行处理,而MobileFFmpeg
则是ffmpeg在移动端的实现,flutter_ffmpeg是对MobileFFmpeg的封装,是的在flutter下能够轻松的使用ffmpeg对音视频进行处理。flutter_ffmpeg包括两部分FFmpeg和FFprobe,其中FFmpeg负责音视频处理,而FFprobe主要负责查询音视频的媒体信息。

flutter_ffmpeg地址

flutter_ffmpeg使用
第一步:安装
// 在pubspec.yaml的dependencies下添加:  flutter_ffmpeg: ^0.3.1
第二步:配置

android工程下的配置

// 在工程目录下的 /android/build.gradle下添加ext {    flutterFFmpegPackage  = "full-lts" }

注意:上面配置中的”full-lts” 是flutter__ffmpeg各个发布版本的报名,可以查看官方文档的说明。有一个值得说明的地方是,flutter_ffmpeg有中发行包,一种是 Main Release,一种是LTS Release 发行包,而他们两者支持的 Android API Level/iOS SDK和硬件架构是不一样的,总的来说,LTS版本支持的更广泛,LTS支持度大于MAIN,所以我们最好使用LTS版本。
这里我遇到一个问题,使用full-lts编码格式,会出现上传到服务器无法播放视频的情况。
所以我这里是用的:

ext {    flutterFFmpegPackage = "full-gpl-lts"}

另外在使用flutter_ffmpeg的时候出现类似问题:

Caused by: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/app.domain.name-Lq_GxP1CfMArHTpLoII-YA==/base.apk"],nativeLibraryDirectories=[/data/app/app.domain.name-Lq_GxP1CfMArHTpLoII-YA==/lib/arm64, /data/app/app.domain.name-Lq_GxP1CfMArHTpLoII-YA==/base.apk!/lib/arm64-v8a, /system/lib64, /system/vendor/lib64]]] couldn't find "libmobileffmpeg_abidetect.so"        at java.lang.Runtime.loadLibrary0(Runtime.java:1011)        at java.lang.System.loadLibrary(System.java:1657)        at com.arthenica.mobileffmpeg.AbiDetect.<clinit>(Unknown Source:13)        at com.arthenica.mobileffmpeg.AbiDetect.getNativeAbi(Native Method)        at com.arthenica.mobileffmpeg.Config.<clinit>(Unknown Source:96)        at com.arthenica.mobileffmpeg.Config.nativeFFmpegExecute(Native Method)        at com.arthenica.mobileffmpeg.b.a(Unknown Source:0)        at d.b.a.a.a.a(Unknown Source:31)        at d.b.a.a.a.doInBackground(Unknown Source:2)        at android.os.AsyncTask$2.call(AsyncTask.java:333)        at java.util.concurrent.FutureTask.run(FutureTask.java:266)        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)         at java.lang.Thread.run(Thread.java:764) 

通过clean可以解决

flutter cleanflutter build [artificat]

使用gpl保证裁剪视频默认使用x264(不然会出现上传视频无法播放的问题),具体可以查看flutter_ffmpeg封装编码

img

image.png

第三步:使用

flutter_ffmpge是ffmpeg在flutter上的一个实现,ffmpeg是通过命令行还进行音视频编辑的工具,因此我们使用fluter_ffmpeg自然也是运行一些命令来实现我们的功能。具体使用方法可以直接看ffluter_ffmpeg官方文档ffmpeg官方文档,或者看一下更加通俗易懂的阮一峰文档。接下来我们主要看看flutter_ffmpeg能干什么?

flutter_ffmpge能做什么?

查看视频信息

做音视频处理,首先我们肯定想知道我们的处理是否成功,或者效果好不好,那么我们只能通过处理的视频前后的参数进行对比,因此第一步我们要求这个视频处理库详细的给我们提供音视频的信息,flutter_ffmpeg的FFProde能够很好的实现这一点,而且使用很方便:

final FlutterFFprobe _flutterFFprobe = new FlutterFFprobe();_flutterFFprobe.getMediaInformation("").then((info) {    print("Media Information");    print("Path: ${info.getMediaProperties()['filename']}");    print("Format: ${info.getMediaProperties()['format_name']}");    print("Duration: ${info.getMediaProperties()['duration']}");    print("Start time: ${info.getMediaProperties()['start_time']}");    print("Bitrate: ${info.getMediaProperties()['bit_rate']}");    Map<dynamic, dynamic> tags = info.getMediaProperties()['tags'];    if (tags != null) {        tags.forEach((key, value) {            print("Tag: " + key + ":" + value + "\n");        });    }    if (info.getStreams() != null) {        List<StreamInformation> streams = info.getStreams();        if (streams.length > 0) {            for (var stream in streams) {                print("Stream id: ${stream.getAllProperties()['index']}");                print("Stream type: ${stream.getAllProperties()['codec_type']}");                print("Stream codec: ${stream.getAllProperties()['codec_name']}");                print("Stream full codec: ${stream.getAllProperties()['codec_long_name']}");                print("Stream format: ${stream.getAllProperties()['pix_fmt']}");                print("Stream width: ${stream.getAllProperties()['width']}");                print("Stream height: ${stream.getAllProperties()['height']}");                print("Stream bitrate: ${stream.getAllProperties()['bit_rate']}");                print("Stream sample rate: ${stream.getAllProperties()['sample_rate']}");                print("Stream sample format: ${stream.getAllProperties()['sample_fmt']}");                print("Stream channel layout: ${stream.getAllProperties()['channel_layout']}");                print("Stream sar: ${stream.getAllProperties()['sample_aspect_ratio']}");                print("Stream dar: ${stream.getAllProperties()['display_aspect_ratio']}");                print("Stream average frame rate: ${stream.getAllProperties()['avg_frame_rate']}");                print("Stream real frame rate: ${stream.getAllProperties()['r_frame_rate']}");                print("Stream time base: ${stream.getAllProperties()['time_base']}");                print("Stream codec time base: ${stream.getAllProperties()['codec_time_base']}");                Map<dynamic, dynamic> tags = stream.getAllProperties()['tags'];                if (tags != null) {                  tags.forEach((key, value) {                    print("Stream tag: " + key + ":" + value + "\n");                  });                }            }        }    }});

视频压缩

  • 改变帧率
ffmpeg -i Desktop/吉他.mp4  -r 20  Desktop/output1.mp4

-r 20:表示帧率设置为 20fps

  • 指定文件大小
ffmpeg -i Desktop/吉他.mp4  -fs 15MB  Desktop/output1.mp4

fs 20 : 表示文件大小最大值为15MB
把视频截了一部分 — 这种方法不推荐

  • 改变分辨率
ffmpeg -i Desktop/1.mov -s vga Desktop/1.mp4

-s vga : 指定分辨率, vga 代表 600*480,也可以换成其他的值

  • 改变码率
    视频的原码率是 2.1Mb/s ,压缩为 1.5Mb/s
ffmpeg -i Desktop/1.mov -b:v 1.5M  Desktop/1.mp4

-b:v 1.5M : 指定码率
-b:v :指定视频的码率
-b:a : 指定音频的码率
1.5M:码率的值 1.5M 表示 1.5Mb/s

裁剪视频

比如我在项目里用到上传到服务器的视频时长需要控制在60s以内的功能,我们就可以这样:

 String inputFilePath = inputFile.path;                    String outputFilePath =                        await FileUtils.outputFileNameStr(inputFile);                    var ffmpeg = new FlutterFFmpeg();                    ffmpeg                        .execute("-i $inputFilePath -ss 0 -to 60 -c:v libx264 $outputFilePath")//这里是ffmpeg指令 裁剪60s视频                        .then((rc) async {                      if (rc == 0) {                        //rc=0表示成功                        //裁剪60s 转换 libx264                      } else {                        showToast('视频裁剪出现异常,请重试', context);                        Navigator.pop(context);                      }                    });

转换视频格式

var ffmpeg = new FlutterFFmpeg();  Directory tempDir = await getTemporaryDirectory();;  var tmpVideo = tempDir.path + '/1.webm';  var cmd = '-i ${widget.tmpPath} $tmpVideo';  print('命令是:'+cmd);  ffmpeg.execute(cmd).then((rc) {    print("处理的结果是:$rc");    if(rc == 0) {      initController(tmpVideo); //使用临时地址可以播放    } else {      print('处理失败');    }  });

下边列出一些常用的ffmpeg指令

视频裁剪

从n开始,裁剪m秒长度的视频

// 从10s开始裁剪连续5s 也就是10-15s的视频ffmpeg -i input.mp4 -ss 10 -t 5 output.mp4

从n秒开始,裁剪到m秒的视频

// 从10s开始,裁剪到20秒ffmpeg -i input.mp4 -ss 10 -to 20 output.mp4
滤镜

https://www.cnblogs.com/tocy/p/ffmpeg-filter-intro.html

叠加两个视频:
ffmpeg -i 1.mp4 -i douyin.mp4 -filter_complex " blend=all_mode='overlay':all_opacity=0.2" blend.mp4
剪切100*100 的视频, 新视频的中心点和输入和视频的重合
ffmpeg -i douyin.mp4  -vf "crop=100:100" crop.mp4
在视频的上画一个框 drawbox
// red@0.5 50%的透明度红色// t=1 线条的粗细 默认3  fill的话 自动填充ffmpeg -i input.mp4 -vf "drawbox=10:10:30:30:red@0.5:t=1" output.mp4ffmpeg -i input.mp4 -vf "drawbox=x=10:y=10:width=30:height=30color=red@0.5:t=1" output.mp4
在视频上画网格 drawgrid
画尺寸是20*20的网格ffmpeg -i 1.mp4 -vf "drawgrid=width=20:height=20:color=red" output.mp4画2*2的网格ffmpeg -i 1.mp4 -vf "drawgrid=width=iw/2:height=ih/2:color=red:t=1:color=blue@0.5" output.mp4
在视频上写字 drawtext
ffmpeg -i 99.mp4 -vf "drawtext=fontsize=32:fontcolor=red:text='hello world':alpha=0.8" font.mp4//前五秒显示 // gte(t\,5) 大于等于5秒// between(t\,5\,10)5到10秒// lt(t\, 5)小于5秒ffmpeg -i 99.mp4 -vf "drawtext=fontsize=32:fontcolor=red:text='hello world':enable='lt(t\,5)' " font.mp4//水平居中 (w-text_w)/2//垂直居中 (h-text_h)/2ffmpeg -i 99.mp4 -vf "drawtext=fontsize=32:fontcolor=#cccccc:text='hello world':x=(w-text_w)/2" font2.mp4//向右对齐 ffmpeg -i 99.mp4 -vf "drawtext=fontsize=32:fontcolor=#cccccc:text='hello world':x=(w-text_w)" font2.mp4// 水平垂直居中ffmpeg -i 99.mp4 -vf "drawtext=fontsize=32:fontcolor=#cccccc:text='hello world':x=(w-text_w)/2:y=(h-text_h)/2" font2.mp4// 滚动文本ffmpeg -i 99.mp4 -vf "drawtext=fontsize=32:fontcolor=#cccccc:text='hello world':x=(w-50*t)" font2.mp4
饱和度/亮度/对比度 eq
// contrast 对比度 -1000-1000// brightness 亮度 -1.0-1.0// saturation 饱和度 0.0-3.0ffmpeg -i 1.mp4 -vf "eq=saturation=3:brightness=0.3:contrast=1000" output.mp4
淡入淡出 fade
// 从第0帧开始到30帧淡入ffmpeg -i 1.mp4 -vf "fade=t=in:s=0:n=30" output.mp4// 从10秒开始淡出5秒ffmpeg -i 1.mp4 -vf "fade=t=out:st=10:d=5" output.mp4
调整帧率 fps
ffmpeg -i 1.mp4 -vf "fps=fps=24" output.mp4
水平翻转视频
ffmpeg -i 1.mp4 -vf "hflip" output.mp4
倒放 reverse
ffmpeg -i input.mp4 -vf "reverse" output.mp4
旋转 rotate
旋转45度ffmpeg -i input.mp4 -vf "rotate=PI/4"转圈圈ffplay -i 99.mp4 -vf "rotate=n*PI/3:c=red"调整输出尺寸 修改输出宽度等于输入宽度的对角线ffplay -i 99.mp4 -vf "rotate=n*PI/3:ow=hypot(iw, ih):oh=ow"
缩放 scale
ffplay -i 99.mp4 -vf "scale=100x100"ffplay -i 99.mp4 -vf "scale=w=0.8*iw:h=0.8*ih"// 宽度为100,iw较小的值 高度等比例缩小ffplay -i 99.mp4 -vf "scale=w=min(100\,iw):h=-1"
合并 concat
// 视频的尺寸要一样大 如果不一样大的话 可以使用pad补边界 ffmpeg -i 1.mp4 -i douyin.mp4 -i 3.1.mp4 -filter_complex "[0:v:0][0:a:0][1:v:0][1:a:0][2:v:0][2:a:0]concat=n=3:v=1:a=1[ov][oa]" -map "[ov]" -map "[oa]" -vsync 2 output.mp4// 图片和视频合并 需要调整视频图片的尺寸和视频一样ffmpeg -loop 1 -framerate 25 -t 5 -i logo.png -i 3.mp4 -filter_complex "[0]scale=1280x720[01];[01][1:v:0]concat=n=2:v=1[ov]" -map "[ov]" 33.mp4ffmpeg -loop 1 -framerate 25 -t 5 -i logo.png -i 3.mp4 -filter_complex "[0]pad=w=1280:h=720:w=(1280-iw)/2:y=(720-ih)/2[01];[01][1:v:0]concat=n=2:v=1[ov]" -map "[ov]" 33.mp4ffmpeg -loop 1 -framerate 29.42 -t 10 -i 1.s.jpg -i 1.mp4 -filter_complex "[0]scale=480:480, setsar=1[im];[1]scale=480:480, setsar=1[iv];[im][1:a][iv][1:a]concat=n=2:v=1:a=1[outv][outa]" -map "[outa]" -map "[outv]" output.mp4// 图片生成视频ffmpeg -f lavfi -t 10 -i anullclass="lazy" data-src -loop 1 -framerate 10 -t 5 -i 1.jpg -vf "scale=664x478" -pix_fmt yuv420p output.mp4// 添加第三条音频 ffmpeg -i im.mp4 -i douyin.mp4 -i 1.mp3 -filter_complex "[0]scale=544x960,setsar=1[iv];[1]setsar=1[dv];[iv][0:a:0][dv][1:a:0]concat=n=2:v=1:a=1[ov][oa]" -map "[ov]" -map "[oa]" -map 2:a:0 -vsync 2 output.mp4ffmpeg -i im.mp4 -i douyin.mp4 -i 1.mp3 -filter_complex "[0]scale=544x960,setsar=1[iv];[1]setsar=1[dv];[iv][0:a:0][dv][1:a:0]concat=n=2:v=1:a=1[ov][oa];[2:a:0][oa]amix=inputs=2:duration=first:dropout_transition=3[aa]" -map "[ov]" -map "[aa]" -vsync 2 output.mp4
提取视频缩略图
// 三秒一张 fps=1/3 ffmpeg -i input.mp4 -vf "fps=1/3, scale=128:72" output_%d.jpg
  >>> 音视频开发 视频教程: https://ke.qq.com/course/3202131?flowToken=1031864   >>> 音视频开发学习资料、教学视频,免费分享有需要的可以自行添加学习交流群 739729163 领取

来源地址:https://blog.csdn.net/weixin_52622200/article/details/131537307

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

【FFmpeg实战】Flutter音视频裁剪

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

使用Golang和FFmpeg实现视频裁剪的技巧

在Golang中,可以使用os/exec包来执行命令行程序,包括FFmpeg。以下是使用Golang和FFmpeg实现视频裁剪的示例代码:```gopackage mainimport ("fmt""log""os""os/exec""st
2023-10-09

Python如何实现视频裁剪

小编给大家分享一下Python如何实现视频裁剪,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!环境依赖本文主要使用到的不是ffmpeg,而是ffprobe也在上面这
2023-06-28

Qt音视频开发之实现ffmpeg视频旋转显示

这篇文章主要为大家详细介绍了在Qt音视频开发中如何利用ffmpeg实现视频旋转显示,文中的实现步骤讲讲清晰,感兴趣的小伙伴可以了解一下
2023-03-22

Qt利用ffmpeg实现音视频同步

这篇文章主要为大家详细介绍了Qt如何利用ffmpeg实现音视频同步的功能,文中的示例代码讲解详细,对大家深入了解Qt有一定的帮助,需要的可以参考一下
2023-01-04

使用Golang和FFmpeg实现视频剪辑的方法

要使用Golang和FFmpeg实现视频剪辑,可以通过调用FFmpeg的命令行工具来完成操作。下面是一个示例的代码:gopackage mainimport ("log""os""os/exec")func main() {// 输入参数i
2023-10-20

python基于moviepy实现音视频剪辑

目录实践步骤完整代码参考实践步骤1.寻找合适的Python库(安装是否麻烦、使用是否简便、执行会不会太久)moviepy 音视频库。分析需要用的API:代码示例2.定义输入输出输入:一个音视频文件的地址,需要剪出来的时间段输出:剪辑片段的文
2022-06-02

Java怎么实现视频自定义裁剪功能

今天就跟大家聊聊有关Java怎么实现视频自定义裁剪功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。前言下面提供将视频按照自定义尺寸进行裁剪的Java工具类,一如既往的实用主义。Ma
2023-06-28

Qt音视频开发之怎么实现ffmpeg视频旋转显示

这篇文章主要介绍了Qt音视频开发之怎么实现ffmpeg视频旋转显示的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Qt音视频开发之怎么实现ffmpeg视频旋转显示文章都会有所收获,下面我们一起来看看吧。一、前言用
2023-07-05

使用Golang和FFmpeg实现视频片段剪辑的技巧

要使用Golang和FFmpeg实现视频片段剪辑,可以使用以下技巧:1. 安装FFmpeg并确保它可以在命令行中使用。2. 在Golang中使用os/exec包调用FFmpeg命令行工具。3. 使用FFmpeg的命令行选项来指定输入视频文件
2023-10-10

AutoJs4.1.0实战教程---凹音短视频

凹音短视频邀请码:VLFQ35又一个区块链大作,昨天刚刚发布,目前公测中。目前一个砖石是7RMB,一个号一天能0.5个。区块链作品前期收益巨大,道友们还犹豫啥呢?直接注册是不能的的扫描二维码注册:单击代码已经写好,分享给道友们:auto.w
2023-06-03

Qt音视频开发之利用ffmpeg实现解码本地摄像头

一开始用ffmpeg做的是视频流的解析,后面增加了本地视频文件的支持,到后面发现ffmpeg也是支持本地摄像头设备的,所以本文就来用ffmpeg实现解码本地摄像头功能吧
2023-03-24

Qt音视频开发之怎么用ffmpeg实现解码本地摄像头

这篇文章主要介绍了Qt音视频开发之怎么用ffmpeg实现解码本地摄像头的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Qt音视频开发之怎么用ffmpeg实现解码本地摄像头文章都会有所收获,下面我们一起来看看吧。相
2023-07-05

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录