FFmpeg研究之路

来源:互联网 发布:中创软件地址 编辑:程序博客网 时间:2024/06/05 09:15

http://chen-shan.net/?p=1371

1.前言:

项目中有需要,将摄像头的视频流进行转换。包括实时流的转换,和本地视频文件的转换。选用FFmpeg这一开源包来完成这一需求,下面是我从零开始的过程。

2.步骤:

一、我先去官网把源码下载到本地,然后看了下目录结构和ffmpeg.c文件中的main函数;并下载了二进制文件,参考这篇文章测试了下将一个h264文件转换成avi格式文件并添加时间戳的功能。

二、然后粗略看了以下几篇文章,了解了FFmpeg的代码基本框架和编解码基本流程:

FFMPEG源码分析

ffmpeg源码分析一:框架

ffmpeg源码分析二:transcode()函数

ffmpeg源码分析三:transcode_init()函数

ffmpeg源码分析之媒体打开过程

ffmpeg源码分析之vfwcap

使用FFMPEG SDK解码流数据

三、分别在Linux系统与OS X系统上编译源码(编译前可能需安装yasm);并阅读FFmpeg Command Line Tool官网文档和ffmpeg命令详解。

四、使用FFmpeg命令

4.1视频格式转换

# 以h264格式转为avi格式,可用于在MP4上播放ffmpeg -i input.h264 -aspect 16:9 -s 1280x720 -r 24 -b:v 10m -bufsize 10m output.avi# 设置横纵比: -aspect 16:9# 设置帧大小: -s 1280x720# 设置帧频(24fps): -r 24# 设置比特率(10Mbps): -b:v 10m# 设置码率控制缓冲区大小: -bufsize 10m
# 以flv格式转换为mov格式,可用于Mac或者iPHone上播放fmpeg -i input.flv -strict -2 output.mov# 使用acc encoder:-strict -2

4.2合成视频

# 将MP3文件与jpg图片合成avi视频文件,这条命令亲测时老出问题:只能显示第一张图片ffmpeg -i music.mp3 -i t-%03d.jpg -s 1024*720 output.avi

4.3按时间切割视频(参考链接1 参考链接2 参考链接3)

ffmpeg -i input.mov -ss 00:00:50 -t 00:00:20 -async 1 -strict -2 output.mov# 设置切割(seeking)开始时间:-ss (00:00:50表示从第50秒开始)# 设置切割的时长:-t (-t 00:00:20表示切割时长为20秒的信息)# Audio sync method:-async

4.4转换rtsp实时视频流(参考链接1 参考链接2)

ffmpeg -i rtsp://10.0.0.101/mpeg4 -aspect 16:9 -s 1280x720 -r 24 -b:v 10m -bufsize 10m -t 00:00:20 -y rtsp.avi# rtsp实时流作为输入:-i rtsp://10.0.0.101/mpeg4# 覆盖已有文件:-y# 捕获时长: -t 00:00:20# 其他参数均在本文前面可以找到对应解释

4.5获取视频信息(参考链接)

# 获取视频信息ffmpeg -i input.avi# 获取视频总时间(注意:前提是该文件有时间戳)ffmpeg -i input.avi 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//

五、C调用示例函数

/* 视频转换函数 (参数传递建议用结构体)*/int videoSwitch() {    /* 设置参数 */    char *ffCommand = "YourCommandPath/bin/ffmpeg";      /* ffMpeg命令路径 */    char *ffInput = "YourInputFilePath/input.h264";      /* 输入文件 */    char *ffAspect = "16:9";            /* 设置横纵比 默认16:9*/    char *ffS = "1280x720";             /* 设置帧大小 默认1280*720*/    char *ffR = "24";                   /* 设置帧频 默认24*/    char *ffBV = "10m";                 /* 设置比特率 默认为10M*/    char *ffBuf = "10m";                /* 设置码率控制缓冲区大小 默认为10M*/    char *ffOutput = "YourOutputFilePath/output.avi";    /* 输出文件 */    /* 执行命令 */    char command[1500];    sprintf(command, "%s -i %s -aspect %s -s %s -r %s -b:v %s -bufsize %s -y %s", ffCommand, ffInput, ffAspect, ffS, ffR, ffBV, ffBuf, ffOutput);    system(command);    return 1;}/* 视频按时间切割函数 */int videoSeeking() {    /* 设置参数 */    char *ffCommand = "YourCommandPath/bin/ffmpeg";      /* ffMpeg命令路径 */    char *ffInput = "YourInputFilePath/input.h264";      /* 输入文件 */    char *ffSS = "00:00:55";    /* 开始时间 */    char *ffT = "00:00:10";     /* 时长 */    char *ffOutput = "YourOutputFilePath/output.avi";    /* 输出文件 */    /* 执行命令 */    char command[1500];    sprintf(command, "%s -i %s -ss %s -t %s -async 1 -strict -2 -y %s", ffCommand, ffInput, ffSS, ffT, ffOutput);    system(command);    return 1;}/* 转换rtsp实时视频流函数 */int videoSwitchOnline() {    /* 设置参数 */    char *ffCommand = "YourCommandPath/bin/ffmpeg";      /* ffMpeg命令路径 */    char *ffInput = "rtsp://10.0.0.104/mpeg4";    /* 输入文件 (rtsp实时流) */    char *ffAspect = "16:9";            /* 设置横纵比 默认16:9*/    char *ffS = "1280x720";             /* 设置帧大小 默认1280*720*/    char *ffR = "24";                   /* 设置帧频 默认24*/    char *ffBV = "10m";                 /* 设置比特率 默认为10M*/    char *ffBuf = "10m";                /* 设置码率控制缓冲区大小 默认为10M*/    char *ffT = "00:00:15";             /* 设置实时流捕获时间 默认15秒钟 */    char *ffOutput = "YourOutputFilePath/output.avi";    /* 输出文件 */    /* 执行命令 */    char command[1500];    sprintf(command, "%s -i %s -aspect %s -s %s -r %s -b:v %s -bufsize %s -t %s -y %s", ffCommand, ffInput, ffAspect, ffS, ffR, ffBV, ffBuf, ffT, ffOutput);    system(command);    return 1;}/* 获取视频的总时间函数 */int videoDuration() {    FILE *fstream=NULL;    char buff[1024];    memset(buff,0,sizeof(buff));    /* 设置参数 */    char *ffCommand = "YourCommandPath/bin/ffmpeg";      /* ffMpeg命令路径 */    char *ffInput = "YourOutputFilePath/output.avi";    /* 输入文件 */    /* 执行命令 */    char command[500];    sprintf(command, "%s -i %s  2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//", ffCommand, ffInput);    fstream = popen(command, "r");    /* 处理输出 */    fgets(buff, 9, fstream);    printf("%s\n",buff);    return 1;}

 


0 0