FFMPEG生成M3U8

at 5个月前  ca FFmpeg  pv 191  by touch  

m3u8是一种视频播放标准,准确来说是一种索引文件,使用m3u8文件实际上是通过它来解析服务器上对应的视频地址。视频网站可以根据用户的网络带宽情况,自动为客户端匹配一个合适的码率文件进行播放,从而保证视频的流畅度。
此代码通过FFMPEG函数将视频文件转换成TS和M3U8文件,可以使用此代码完成点播业务。

#include <iostream>
#include <string>
#include <fstream>
#include <thread>
#include <functional>

extern "C"{
#include <libavformat/avformat.h>
#include <libavutil/pixdesc.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
};


void printError(int code)
{
    char buf[1024]={0};
    av_strerror(code,buf,sizeof(buf));
    std::cout << "error msg :" << buf << std::endl;
}


AVFormatContext* createFmtCtx(AVFormatContext *inFmtCtx,char*  outMediaFilePath){

    AVFormatContext *outFmtCtx=avformat_alloc_context();
    avformat_alloc_output_context2(&outFmtCtx, NULL, NULL, outMediaFilePath);
    int videoStrIndex=av_find_best_stream(inFmtCtx,AVMEDIA_TYPE_VIDEO,-1,0,NULL,0);
    int audioStrIndex=av_find_best_stream(inFmtCtx,AVMEDIA_TYPE_AUDIO,-1,0,NULL,0);

    AVStream *videoStream=avformat_new_stream(outFmtCtx,NULL);
    AVStream *audioStream=avformat_new_stream(outFmtCtx,NULL);

    avcodec_parameters_copy(videoStream->codecpar,inFmtCtx->streams[videoStrIndex]->codecpar);
    avcodec_parameters_copy(audioStream->codecpar,inFmtCtx->streams[audioStrIndex]->codecpar);
    avcodec_parameters_to_context(videoStream->codec,videoStream->codecpar);
    avcodec_parameters_to_context(audioStream->codec,audioStream->codecpar);

    if (avio_open(&outFmtCtx->pb, outMediaFilePath, AVIO_FLAG_READ_WRITE) < 0) //创建并初始化一个AVIOContext
    {
        std::cout << "avio_open error msg " << std::endl;
        return NULL;
    }

    av_dump_format(outFmtCtx, 0, outMediaFilePath, 1);
    return outFmtCtx;
}



int main()
{
    av_register_all();
    //视频编码主要格式h264/mpeg4,音频为acc/MP3。
    //输入视频文件路径
    const char* inputMediaFilePath="D:\\1\\1.flv";

    //使用指针,方便后面修改文件名称
    AVFormatContext  *pFmtCtx=avformat_alloc_context();
    int ret=avformat_open_input(&pFmtCtx,inputMediaFilePath,NULL,NULL);
    if(ret!=0)
    {
        printError(ret);
        return 0;
    }
    ret=avformat_find_stream_info(pFmtCtx,NULL);
    if(ret!=0)
    {
        printError(ret);
        return 0;
    }


    AVPacket *pkt=av_packet_alloc();

    //文件m3u8
    char outFileName[]="D:\\1\\ts\\test.m3u8";

    //https://www.ffmpeg.org/ffmpeg-all.html#hls-2
    AVDictionary* muxer_opts = NULL;
    //event vod
    av_dict_set(&muxer_opts, "hls_playlist_type", "vod", 0);
    //生成ts分段文件的路径
    av_dict_set(&muxer_opts, "hls_segment_filename", "D:\\1\\ts\\test_%05d.ts", 0);
    //hls_time 参数设置切片的duration,单位秒
    av_dict_set(&muxer_opts,"hls_time","10",0);
    av_dict_set(&muxer_opts,"hls_list_size","0",0);
    //每隔10秒刷新一次m3u8
    av_dict_set(&muxer_opts,"master_pl_publish_rate","2",0);
    AVFormatContext* outFmtCtx=createFmtCtx(pFmtCtx,outFileName);
    avformat_write_header(outFmtCtx, &muxer_opts);

    while (av_read_frame(pFmtCtx, pkt) >= 0) {
        av_interleaved_write_frame(outFmtCtx, pkt);
        av_packet_unref(pkt);
    }

    av_write_trailer(outFmtCtx);
    av_packet_free(&pkt);
    avformat_close_input(&pFmtCtx);
    avformat_free_context(pFmtCtx);
    return 0;
}


版权声明

本文仅代表作者观点,不代表码农殇立场。
本文系作者授权码农殇发表,未经许可,不得转载。

 

扫一扫在手机阅读、分享本文

已有0条评论