百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

Android 接入FFmpeg命令-低成本完成各类音视频操作

xsobi 2024-12-25 16:14 1 浏览

一、导入资源和编译

1.1、导入相关源文件

FFmpge源码下有一个fftools目录,里面就是一些ffmpeg的命令行程序,我们将他们导入进来,进行一定的修改后再自行编译成我们的lib。

首先是对库文件进行相应的修改,因为ffmpeg.c在windows上的目的是编译成一个可执行的应用,所以它的入口是main 通过命令行传参,所以我们这里需要把main函数改一下,改成一个我们具体功能的名字,例如我喜欢叫它exc,然后再再头文件中声明我们刚改的函数名,这样它就变成了一个库文件。我们在jni的地方调用exc进行传参,就达到了电脑端命令行的效果。

还有一个地方,ffmpeg如果指令执行出错是执行的退出程序指令,我们在Android端肯定不行,那不然指令执行不成功就一个闪退这谁都顶不住,所以我们需要把exit_program函数的exit(ret);去掉,这里我们可以做我们自己的逻辑,进行自己的错误码回调。

【更多音视频学习资料,点击下方链接免费领取↓↓,先码住不迷路~】

音视频开发基础知识和资料包

原代码

void exit_program(int ret)

{

if (program_exit)

program_exit(ret);

exit(ret);

}

修改后

void exit_program(int ret)

{

if (program_exit)

program_exit(ret);

}

编译过程中发现会有些库丢失,可以删掉也可以把库引进来.主要看这些库是否是你所需要的功能,例如有些是一些打印函数缺失的我不需要我就直接删掉也懒得导包了。

1.2、cmdkelist的编写

首先是引入头文件目录 以我的文件目录为例我的为 include_directories(ffmpeg/fftools),后续的依赖完整如下:

add_library( # Sets the name of the library.

ffmpeg-cmd

# Sets the library as a shared library.

SHARED

# Provides a relative path to your source file(s).

ffmpeg/fftools/cmdutils.c

ffmpeg/fftools/ffmpeg.c

ffmpeg/fftools/ffmpeg_opt.c

ffmpeg/fftools/ffmpeg_filter.c

ffmpeg/fftools/ffmpeg_hw.c

ffmpeg-cmd.c

)


target_link_libraries( # Specidefies the target library.

ffmpeg-cmd

# Links the target library to the log library

# included in the NDK.

fdk-aac

mp3lame

avdevice

postproc

avfilter

avformat

avcodec

avutil

swresample

swscal

)

cmdutils.c、ffmpeg.c、ffmpeg_opt.c、ffmpeg_filter.c、ffmpeg_hw.c、ffmpeg-cmd.c都有一定的依赖关系,这几个C文件共同编译成一个库ffmpeg-cmd,ffmpeg-cmd是我的JNI层方法,负责双边沟通,fftools中依赖了其它例如解码,滤镜,重采样等外部库,也是我们之前编译了的其它库,我们需要把它们作为ffmpeg-cmd的库链接进去。

二、加入执行回调

对于命令的执行很多时候是一个耗时操作,我们UI不可能在那里干等,所以我们需要给命令执行加入回调,告诉Java层指令的执行状态,好做一些进度的变更,成功或失败的处理。最基本的我们给指令执行加入进度,失败,成功的回调。

2.1、执行进度回调

ffmpeg.c里有一个print_report方法,里面主要是一个它自身进度的打印,我们看其中一段主要代码

【更多音视频学习资料,点击下方链接免费领取↓↓,先码住不迷路~】

C++程序员必看,抓住音视频开发的大浪潮!冲击年薪60万

static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time)

{

......

secs = FFABS(pts) / AV_TIME_BASE;

us = FFABS(pts) % AV_TIME_BASE;

mins = secs / 60;

secs %= 60;

hours = mins / 60;

mins %= 60;

hours_sign = (pts < 0) ? "-" : "";

//program_progress(secs); //本身没有,这是我们自己加的,这是简单逻辑,可以自己再写逻辑

bitrate = pts && total_size >= 0 ? total_size * 8 / (pts / 1000.0) : -1;

speed = t != 0.0 ? (double)pts / AV_TIME_BASE / t : -1;

......

}

在这里它计算出了已经执行完成的文件时长,同样的我们传入函数指针,把这个时长传到Java层,稍加计算就能得到我们需要的进度。

//ffmpeg.h

/**

* Register a register_progress.

*/

void register_progress(void (*cb)(long progress));

//ffmpeg.c

static void (*program_progress)(long progress);

void register_progress(void (*cb)(long progress))

{

program_progress = cb;

}


2.1、执行成功/失败回调

不管成功还是失败,ffmpeg都会走void exit_program(int ret) 方法,它自身会先走一个ffmpeg_cleanup方法,做一些他自己的收尾工作。我们可以在它自身方法的后面插入我们自己的回调方法,就是我们自己传入一个函数指针,其实就是我们重写一个相同签名的方法然后把这个方法的地址传过去,程序自己进行地址切换,跳转执行。回调0表示成功,回调其它表示失败。

//cmdutils.h

/**

* Register a register_status.

*/

void register_status(void (*cb)(int ret));

//cmdutils.c

static void (*program_status)(int ret);

void register_status(void (*cb)(int ret))

{

program_status = cb;

}

void exit_program(int ret)

{

if (program_exit)

program_exit(ret);

if (program_status)//加入我们的状态回调

program_status(ret);

}

使用时我们把这两个函数指针传进去即可。执行一段命令就会有进度和状态的回调,我们可以把它展示到UI上。

static void exit_call(int ret){

LOGE("exit_call %d", ret);

}

static void cmd_progress(long progress){

LOGE("onProgress %d", progress);

}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){

JNIEnv* jniEnv= NULL;

int result=(*vm)->GetEnv((vm),(void **)&jniEnv,JNI_VERSION_1_4);

if (result!=JNI_OK){

return -1;

}

av_log_set_callback(log_callback_test2);

register_status(exit_call);//传入函数指针

register_progress(cmd_progress);//传入函数指针

return JNI_VERSION_1_4;

}

三、常见音频操作命令

当然命令还是得看FFmpeg官方文档,但是官方有些好像并没有中文文档,大家可以找找中文翻译的。我这里列出几个我在用的一些命令,包括音频操作和音频滤镜,其余的大家可以自由发挥。

//在任意位置混音

//"ffmpeg -i %s -i %s -filter_complex " +"[1]adelay=delays=%s|%s[aud1];[0][aud1]amix=inputs=2 -y %s";

/**

* 音频操作

*/

//裁剪

private final String cropCmd="ffmpeg -i %s -ss %s -t %s -acodec copy %s";

//pcm转MP3

private final String pcm2Mp3="ffmpeg -f s16le -ar 44100 -ac 2 -i %s -ar 44100 -ac 2 -y %s";

//静音移除 大于间隔0.3s的静音全部移除

private final String muteRemove="ffmpeg -i %s -af silenceremove=stop_periods=-1:stop_duration=0.3:stop_threshold=-30dB %s";

private final String highPassCmd="ffmpeg -i %s -af highpass=300 %s";//低切300 150 75

private final String gateCmd="ffmpeg -i %s -filter agate=knee=1:ratio=1.5:range=0.08 %s";//降噪

/**

* chorus例子

* 一个延迟(二人合唱效果):

* chorus=0.7:0.9:55:0.4:0.25:2

* 2个延迟(三人合唱效果):

* chorus=0.6:0.9:50|60:0.4|0.32:0.25|0.4:2|1.3

* 3个延迟(四人及更多合唱效果):

* chorus=0.5:0.9:50|60|40:0.4|0.32|0.3:0.25|0.4|0.3:2|2.3|1.3

*/

private final String chorusCmd="ffmpeg -i %s -filter chorus=0.6:0.9:50|60:0.4|0.32:0.25|0.4:2|1.3 %s";//三人合唱效果 没什么效果

/**

* 滤镜

*/

private final String echoMountainCmd="ffmpeg -i %s -filter aecho=0.8:0.9:1000:0.3 %s";//山间回音特效

private final String echoRobotCmd="ffmpeg -i %s -filter aecho=0.8:0.88:6:0.4 %s";//机器人特效

private final String afadeCmd="ffmpeg -i %s -filter afade=t=%s:ss=%:ns=%ld:st=%d:d=%d:curve=tri %s";

private final String volumeCmd="ffmpeg -i %s -filter volume=%s %s";//音量

private final String vibratoCmd="ffmpeg -i %s -filter vibrato=f=%f:d=%f %s";//颤音

private final String asetrateCmd="ffmpeg -i %s -filter asetrate=sample_rate=%s,atempo=%s %s";//男低音 30000 1.25变调 44100

private final String asetrate2Cmd="ffmpeg -i %s -filter asetrate=sample_rate=%s,atempo=%s %s";//娃娃音 73500 0.6 44100

private final String atempo2Cmd="ffmpeg -i %s -filter atempo=%s %s";//变速

private final String karaokeCmd="ffmpeg -i %s -filter stereotools=mlev=0.015625 %s";//卡拉OK

private final String compandCmd=""ffmpeg -i %s -filter compand=.3|.3:1|1:-90/-60|-60/-40|-40/-30|-20/-20:6:0:-90:0.2 %s";//感觉像声音加强了

private final String flangeCmd="ffmpeg -i %s -filter flanger=delay=0 %s";//环绕效果

如果你对音视频开发感兴趣,觉得文章对您有帮助,别忘了点赞、收藏哦!或者对本文的一些阐述有自己的看法,有任何问题,欢迎在下方评论区讨论!

相关推荐

【互联网那些事】高效开发Android App的10个建议

  假如要GooglePlay上做一个最失败的案例,那最好的秘诀就是界面奇慢无比、耗电、耗内存。接下来就会得到用户的消极评论,最后名声也就臭了。即使你的应用设计精良、创意无限也没用。  耗电或者内存...

手机APP开发方式有哪些? 手机app的开发模式有哪三种?

微信小程序开发定制_软件开发_APP开发_网站制作-优软软件开发...

Android开发入门(一):Android系统简介

Android系统是Google公司在2008年推出的一款智能移动设备操作系统,通过不断地版本迭代,目前已经推出到Android11版本了。Android系统广泛应用在手机、平板、电视等各种电子设...

物联网app开发流程 物联网app开发工具

现在随着科技的发展,很多产品都想用一个手机app去显示他的参数数据或者通过手机app去控制它。但是很多人不知道他的流程。今天我就来说下物联网app开发流程。首先需要把物联网app开发流程分2个步骤,一...

Android开发进阶 | 如何学习 Android Framework?

大部分有“如何学习Framework源码”这个疑问的,应该大都是应用层开发。应用层是被Framework层调用执行的,知道自己的代码是怎么被调用的,才能理解程序的本质,理解本质有助于解决遇到的...

快速实现APP混合开发(Hybrid App开发)攻略

前言:...

三个阶段带你了解一款app开发的完整流程

第一个阶段需求阶段:1.需求讨论--开发类型、开发平台、具体的产品功能需求、项目预计完成时间、预算2.需求评估--确认合作后评估具体的预算3.界面设计--设计部门进行产品界面设计,形成效果图...

Android 开发中文引导-应用小部件

应用小部件是可以嵌入其它应用(例如主屏幕)并收到定期更新的微型应用视图。这些视图在用户界面中被叫做小部件,并可以用应用小部件提供者发布。可以容纳其他应用部件的应用组件叫做应用部件的宿主(1)。下面的截...

手机软件开发从零开始【Android第2篇Hello】

Hello,朋友们我们又见面了。上一篇我们讲到了《Android开发环境搭建【Android基础第1篇】》,错过的朋友可以点击文章末尾的“阅读原文”查看。另外需要下载JDK和ADT-bundle工具的...

「全栈工程师之梦的开始--安卓开发(二)」开发安卓app

在配置好jdk开发环境、安装好开发工具Androidstudio后,我们就可以开始开发安卓app了。首先,我们需要先了解下android的术语。...

二、Android界面开发 android 开发

学习目标了解Android常用布局了解Android常用控件...

如何开发一款APP既快捷也简便 开发一款app的步骤

具体较为简单的步骤可以选择用androidstudio开发app1、打开软件,在菜单中选择file-》newproject打开创建向导。2、配置项目,确定各个名称和存放项目的存放路径;Applic...

安卓开发中的“Android高手”,需要具备哪些技术?

前言成为一名安卓开发者很容易,但是要成为一名“Android高手”却不那么容易;...

移动开发(一):使用.NET MAUI开发第一个安卓APP

对于工作多年的C#程序员来说,近来想尝试开发一款安卓APP,考虑了很久最终选择使用.NETMAUI这个微软官方的框架来尝试体验开发安卓APP,毕竟是使用VisualStudio开发工具,使用起来也...

微软推出PowerApps:零基础开发Win10/iOS/安卓企业应用

IT之家讯微软今天面向企业宣布了全新的应用开发解决方案PowerApps,让Windows(包括Win10)、iOS以及安卓应用的开发和分发变得更加简单。PowerApps的用户界面与Office办...