ffmpeg 保存MP4后前端无法打开,并且缺失宽高等基础信息

最近采用ffmpeg做一个流媒体服务器,当录像的时候,前端反应无法打开mp4,仔细一看文件也没有缩略图,通过VLC发现可以打开播放,然后用ffmpeg命令查看了一下格式如下:

ffprobe -show_format 2020.mp4
Input #0, mpegts, from '2020.mp4':
  Duration: 00:02:15.04, start: 0.000000, bitrate: 4410 kb/s
  Program 1 
    Metadata:
      service_name    : Service01
      service_provider: FFmpeg
    Stream #0:0[0x100]: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p(progressive), 2560x1440, 25 fps, 25 tbr, 90k tbn, 180k tbc
[FORMAT]
filename=2020.mp4
nb_streams=1
nb_programs=1
format_name=mpegts
format_long_name=MPEG-TS (MPEG-2 Transport Stream)
start_time=0.000000
duration=135.040000
size=74448896
bit_rate=4410479
probe_score=50
[/FORMAT]

猛地一看也没看出什么不对,
然后windows右键属性看了一下:
在这里插入图片描述
发现什么信息都没有,
再用linux打开看一下:
在这里插入图片描述
注意到这里Container是ts格式,难道格式不对?
想到的第一个办法是用MP4info工具打开看一下
结果是open failed.

那就找一个前端能打开的对比一下,
然后找了一个能打开的MP4文件,发现格式如下:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '2020.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1iso6mp41
    encoder         : Lavf58.32.104
  Duration: 00:00:57.20, start: 0.000000, bitrate: 601 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x480, 598 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc (default)
    Metadata:
      handler_name    : VideoHandler
[FORMAT]
filename=2021.mp4
nb_streams=1
nb_programs=0
format_name=mov,mp4,m4a,3gp,3g2,mj2
format_long_name=QuickTime / MOV
start_time=0.000000
duration=57.200000
size=4301534
bit_rate=601613
probe_score=100
TAG:major_brand=isom
TAG:minor_version=512
TAG:compatible_brands=isomiso2avc1iso6mp41
TAG:encoder=Lavf58.32.104

在这里插入图片描述
在这里插入图片描述
果然是格式不对导致,这样就好办了,查看代码发现,我在打开输出的时候用这样,

nRet = avformat_alloc_output_context2(&m_outputFmtContext, nullptr, "mpets",
                                            m_rtmpUrl.c_str());

那应该问题就出现在这里,既然手动行不通,那么就用自动:

m_rtmpUrl=2020.MP4”;
AVOutputFormat *const output_format =
          av_guess_format(nullptr, m_rtmpUrl.c_str(), nullptr);
      if (!output_format) {
        printf("output format not found\n");
        break;
      }
      nRet = avformat_alloc_output_context2(&m_outputFmtContext, output_format,
                                            nullptr, nullptr);
      if (nRet < 0) {
        AVPrintErr(nRet, "avformat_alloc_output_context2");
        break;
      }

修改以后发现还不行,我艹,开始百度了一下,
https://github.com/horgh/videostreamer/blob/master/videostreamer.c
https://blog.csdn.net/ET_Endeavoring/article/details/77949850?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-8.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-8.control

在编码阶段添加如下:

 pAVCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
  pAVCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
  pAVCodecCtx->width = m_width;
  pAVCodecCtx->height = m_height;
  pAVCodecCtx->time_base.num = 1;
  pAVCodecCtx->time_base.den = 25;
  pAVCodecCtx->framerate.den = 1;
  pAVCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
  pAVCodecCtx->bit_rate = 200000;
  pAVCodecCtx->gop_size = 10;
  pAVCodecCtx->keyint_min = 100;
  pAVCodecCtx->qmin = 10;
  pAVCodecCtx->qmax = 36;
  pAVCodecCtx->has_b_frames = 0;

  av_opt_set(pAVCodecCtx->priv_data, "profile", "high", 0);
  av_opt_set(pAVCodecCtx->priv_data, "preset", "slow", 0);
  av_opt_set(pAVCodecCtx->priv_data, "level", "5", 0);
  av_opt_set(pAVCodecCtx->priv_data, "tune", "zerolatency", 0);

Ok,试了一下能打开,但是没有时长,后来觉得是尾部没写,那就把尾部写上:

av_write_trailer(m_outputFmtContext);

发现还是没有时长,不过前端已经可以打开,那就先这样吧,以后解决。
花费了半天功夫。


版权声明:本文为weixin_43360707原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。