利用FFmpeg转码生成MP4文件
2017年06月24日 14:42:53

阅读数:2401

项目中,需要把一路音频流及一路视频流分别转码,生成指定格式(MP4)文件。在使用ffmpeg转码生成mp4文件的过程中,碰到了不少的问题,主要如下:
1. 生成的mp4文件无法正常播放
2. 生成的mp4,用ffmpeg分析,发现码率、帧率等参数不对(编码后的pkt结构体无pts,手动赋值错误,如果是mp4文件,不考虑B帧的情况下,pts是按512往上累加,如果是ts文件,则是按3600累加)
3. 生成的mp4文件,没有声音(编码后的pkt结构体无pts,手动赋值错误,如果是AAC文件,pts按1024累加)

在利用ffmpeg转码的时候,首先要初始化一些结构体,在生成一个MP4文件的时候,也需要创建并初始化一些结构体,具体为:

int open_out_put(const char* filename)
{int ret, i;int video_index = 0;int audio_index = 1;AVStream *out_stream;//编码参数的上下文AVCodecContext *enc_ctx;AVCodec *encoder;//这个参数最为重要,AVFormatContxt*,它为全局变量,该函数主要目的就是初始化它ofmt_ctx = NULL;//为ofmt_ctx申请空间avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);if(ofmt_ctx == NULL){av_log(NULL,AV_LOG_ERROR,"Could not create output context\n");return AVERROR_UNKNOWN;}//申请好空间之后,现在开始需要为它添加音频流及视频流了int nb_streams = 2;for(i = 0; i < nb_streams; i++){//在ofmt_ctx结构体中添加一路媒体流,这路流的实际参数通过out_stream来设置out_stream = avformat_new_stream(ofmt_ctx, NULL);if(!out_stream)//添加流失败了{av_log(NULL,AV_LOG_ERROR,"Failed allocating output stream\n");return AVERROR_UNKNOWN;}//获取这路流的编码参数结构体的指针,然后初始化它enc_ctx = out_stream->codec;if(i == video_index){//添加了第一路流,认为它是视频流encoder = avcodec_find_encoder(AV_CODEC_ID_H264);if(!encoder){av_log(NULL,AV_LOG_ERROR,"Video encoder not found\n");return AVERROR_UNKNOWN;}enc_ctx->bit_rate = 2000000;//2M码率enc_ctx->width = 1920;enc_tx->height = 1080;enc_ctx->time_base = (AVRational)(1,25);//说明帧率为25fpsenc_ctx->gop_size = 50;enc_ctx->pix_fmt = AV_PIX_FMT_YUV420P;enc_ctx->thread_count = 2;//编码器的线程数,正常情况下可以使编码速度变快av_opt_set(enc_ctx->priv_data,"preset","untrafast",0);}else if(i == audio_index){//添加了第二路流,认为它是音频流encoder = avcodec_find_encoder(AV_CODEC_ID_AAC);if(!encoder){av_log(NULL,AV_LOG_ERROR,"Audio encoder not found\n");return AVERROR_UNKNOWN;}enc_ctx->sample_rate = 44100;enc_ctx->channels = 2;enc_ctx->channel_layout = av_get_default_channel_layout(enc_ctx->channels);enc_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;//根据实际的编码格式来设置,AAC为该值enc_ctx->time_base = (AVRational){1,44100};enc_ctx->bit_rate = 128000;}//初始完各个流的编码参数之后,该设置其它媒体文件相关的参数了//ofmt_ctx->oformat结构体的值,根据filename的后缀名不同而有所不同,记住,这个判断在放在avcodec_open2之前,否则就算判断了,也不会生效,最终生成的mp4文件,无法正常播放if(ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;ret = avcodec_open2(enc_ctx, encoder, NULL);}av_dump_format(ofmt_ctx, 0, filename, 1);if(!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)){ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);if(ret < 0){av_log(NULL,AV_LOG_ERROR,"Could not open output file\n");return ret;}}AVDictionary *opt = NULL;//设置媒体文件的视频帧率信息av_dict_set_int(&opt, "video_track_timescale",25, 0);ret = avformat_write_header(ofmt_ctx, &opt);if(ret < 0){av_log(NULL,AV_LOG_ERROR,"Write file header failed\n");return ret;}return 1;
}
  • 14
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97

初始化好了之后,就开始编码了,编码成功后,调用函数

av_interleaved_write_frame(ofmt_ctx, &pkt);1

把编码成功后的数据写入媒体文件中。
当编码结束后,再调用函数

av_write_trailer(fmt_ctx);1

如果没调用此函数写入文件尾部,生成的mp4文件无法正常播放。
最后记得释放fmt_ctx结构体的内存空间。

利用FFmpeg转码生成MP4文件相关推荐

  1. 解决ffmpeg生成mp4文件不能正常预览的问题

    框架的使用极大的提高了开发效率,让我们能够有更多的精力去关注系统的整体架构和业务需求,而不需要过多的关注一些具体的实现细节,但任何事情都有两面性,如果某个细节出了问题,由于对具体的实现不了解,那么会给 ...

  2. Java 利用ffmpeg工具实现视频MP4转m3u8

    Java 利用ffmpeg工具实现视频MP4转m3u8(一) 前言 (一)ffmpeg工具转码 1.如何安装ffmpeg工具 2.如何使用ffmpeg工具进行视频转码 (二)播放m3u8文件 1.vi ...

  3. ffmpeg转码生成的m3u8格式详解

    目录 一.ffmpeg转码生成的单码率和多码率的文件列表 二.Master Playlist主列表(name.m3u8) 1. 单码率(video_single_bitrate.m3u8 ) 2. 多 ...

  4. cfiledialog对话框大小_利用MFC的CFileDialog生成Windows2000文件对话框 (转)

    利用MFC的CFileDialog生成Windows2000文件对话框 (转)[@more@] 利用MFC的CFileDialog生成windows2000文件对话框 周鸣扬 自Windows2000 ...

  5. 【收藏】Python利用Excel+模板批量生成word文件

    Python利用Excel+模板批量生成word文件 最近帮朋友批量生成小区业主物业费未缴的律师函.朋友那有物业那边的表格数据,包括楼栋-房间号.业主姓名.欠费日期.欠款金额等信息.目的是需要将这些表 ...

  6. Android中如何提取和生成mp4文件

    1. MediaExtractor 该类主要用于音视频混合数据的分离,接口比较简单,首先要通过setDataSource(String path)函数设置数据源,数据源可以是本地文件地址,也可以使用H ...

  7. 安卓采集摄像头画面生成MP4文件

    主要用的安卓类有MediaCodec和MediaMuxer,MediaCodec负责视频数据编解码,MediaMuxer负责将编码后的数据封装成MP4文件,采集摄像头用的是camera,并且用surf ...

  8. oxygen 生成java对象_利用oxygen编辑并生成xml文件,并使用JAVA的JAXB技术完成xml的解析...

    首先下载oxygen软件(Oxygen XML Editor),目前使用的是试用版(可以安装好软件以后get trial licence,获得免费使用30天的权限,当然这里鼓励大家用正版软件!!!) ...

  9. FluentData-新型轻量级ORM 利用T4模板 批量生成多文件 实体和业务逻辑 代码

    FluentData,它是一个轻量级框架,关注性能和易用性. 下载地址:FlunenData.Model 利用T4模板,[MultipleOutputHelper.ttinclude]批量生成多文件 ...

最新文章

  1. 搜索引擎的两大问题(1) - 召回
  2. 三次元风景照秒变宫崎骏动画,还能把石原里美吉卜力化,AnimeGAN已开源
  3. java keygenerator_spring-cache -KeyGenerator自定义
  4. 【干货集锦】如何轻松玩转文档管理工具?我们为你精心准备了一份学习大礼包...
  5. docker选择安装位置_监控摄像机的安装位置选择和焦距选择
  6. [蓝桥杯][2013年第四届真题]买不到的数目(动态规划)
  7. 为什么要使用PreparedStatement
  8. php post api json数据,php – REST API:请求身份为JSON或纯POST数据?
  9. redis在php中的应用(string篇)
  10. 【操作系统】用户可通过三种方式使用计算机
  11. android读写串口
  12. vue 父组件调用子组件内置方法
  13. SSH免密登陆:Win登陆linux
  14. 用计算机能算重量加权平均长度吗,利用计算器求平均数检测试题与*
  15. 【干货分享】使用Inno Setup设计扁平化风格的安装包
  16. 后缀001,002,003等的文件解压
  17. 要么到岗,要么离职!马斯克:特斯拉「远程办公」到此结束
  18. 怎样绘制精美的思维导图
  19. 《乔布斯传》阅读感悟
  20. VS2010 常用快捷键 看到不错,收了

热门文章

  1. 后端接口如何接受对象数组
  2. 使用coding和hexo快速搭建博客
  3. 男友布置的任务之-JS红宝书每日一讲
  4. HappyPack not work in webpack 4
  5. r语言删除csv中na行_R中去除为NA的行--转载
  6. django配置环境linux,linux环境下Django的安装配置详解
  7. 【NAS】NFS协议介绍
  8. 时间戳转换时间总是会差几个小时
  9. template.js前端模板引擎使用
  10. 肿瘤NGS测序行业背景介绍