FFmpeg研究之路

80 篇文章 1 订阅

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
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
敬告:本课程基于最新版FFmpeg4.3.1开发,仅供学习参考,不可以直接商用(想直接购买商用源代码的同学,请放弃!)。我将带领大家从以下几个方面来深入剖析ffmpeg4.3:“拿来主义”、“为我所用”。通过学习本课程,您将收获:三大多媒体框架(DirectShow、GStreamer、FFmpeg)简介与分析FFmpeg4.3的开发环境搭建(重要讲解windows下的源码编译及vs2015的环境)ffmpeg.c(4.3.1)源码剖析(分析开源大师们的设计理念和编码技巧)亲手封装私有函数:获取音视频流信息(类似于MediaInfo)、获取实时转码进度(改善用户体验)两套实现代码: MFC和Qt。-------------------------------------------------------------------音视频是一门很复杂的技术,涉及的概念、原理、理论非常多,很多初学者不学 基础理论,而是直接做项目,往往会看到c/c++的代码时一头雾水,不知道代码到底是什么意思,这是为什么呢? 因为没有学习音视频的基础理论,就比如学习英语,不学习基本单词,而是天天听英语新闻,总也听不懂。所以呢,一定要认真学习基础理论,然后再学习播放器、转码器、非编、流媒体直播、视频监控、等等。 梅老师从事音视频与流媒体行业18年;曾在永新视博、中科大洋、百度、美国Harris广播事业部等公司就职,经验丰富;曾亲手主导广电直播全套项目,精通h.264/h.265/aac,曾亲自参与百度app上的网页播放器等实战产品。目前全身心自主创业,主要聚焦音视频+流媒体行业,精通音视频加密、流媒体在线转码快编等热门产品。  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值