转自:FFmpeg研究之路,保存在此以学习。
1.前言:
项目中有需要,将摄像头的视频流进行转换。包括实时流的转换,和本地视频文件的转换。选用FFmpeg这一开源包来完成这一需求,下面是我从零开始的过程。
2.步骤:
一、我先去官网把源码下载到本地,然后看了下目录结构和ffmpeg.c文件中的main函数;并下载了二进制文件,参考这篇文章测试了下将一个h264文件转换成avi格式文件并添加时间戳的功能。
二、然后粗略看了以下几篇文章,了解了FFmpeg的代码基本框架和编解码基本流程:
ffmpeg源码分析三:transcode_init()函数
三、分别在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
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
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; }