FFmpeg研究之路

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

转自:FFmpeg研究之路,保存在此以学习。

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值