# 视频开发入门

# 基本概念

# 容器

视频文件本身是一个容器,里面包含了视频和音频,也可能有字幕等内容 常见的容器格式有以下几种,一般来说,视频文件的后缀名就是它的容器格式

MP4
MKV
WebM
AVI
RMVB
TS
FLV
# 查看ffmpeg支持的容器格式
ffmpeg -formats

# 编码格式

# 常见视频编码格式
VC-1
MPEG2
# 有版权,免费使用
H.262
H.264
H.265  # 解码免费,编码收费
# 无版权
VP8
VP9
AVI
# 常见音频编码格式
AAC
MP3
AC-3
# 视频像素数据
UIV420P
RGB
# 音频
PCM
# 查看ffmpeg支持的编码格式
ffmpeg -codecs

# 编码器

常见视频编码器(FFmpepg 内置)

  • libx264 开源的 H264 编码器(常用)
  • nvenc Nvidias 硬件加速的 H264 编码器
  • libx265 开源 H265 编码器
  • libvpx 谷歌的 VP8 VP9
  • libaom AV1

常见音频编码

  • libfdk-aac
  • aac (常用)
  • opus
  • pcm_u8

# 编码器
ffmpeg -encoders
# 解码器
ffmmeg -decoders

# 视频解码知识

纯粹视频解码流程

压缩编码数据 --> 像素数据

常见视频解码流程

解封装 --> 提取视频码流 --> 视频数据

# Visual Studio 开发环境搭建

新建控制台工程

文件--> 新建项目 --> Win32 控制台应用程序

拷贝 FFmpeg 开发文件

*.h 拷贝到 include *.lib 拷贝到 lib *.dll 拷贝到项目根目录

MinGW

  • inttypes.h
  • stdint.h
  • _mingw.h

配置静态链接库

属性 --> 链接器 --> 输入 --> 附加依赖项

avcodec.lib;avformat.lib;avutil.lib;avdevice.lib;avfilter.lib;postproc.lib;swresample.lib;swscale.lib;

# FFmpeg 库简介

  • avcodec 编解码
  • avformat 封装处理
  • avfilter 滤镜特效
  • avdevice 设备输入输出
  • avutil 工具库
  • postproc 后加工
  • swresample 音频采样格式转换
  • swscale 视频像素数据格式转换

# FFmpeg 数据结构分析

  • AVFormatContext

    • iformat AVInputFormat
    • nb_streams 输入视频的 AVStream 个数
    • streams AVStream[]
    • duration 输入视频的时长
    • bit_rate 输入视频的码率
  • AVInputFormat

    • id
    • name
    • long_name
    • extensions
    • 一些函数
  • AVStream

    • id 序号
    • codec AVCodecContext
    • time_base 时基
    • r_frame_rate 帧率
  • AVCodecContext

    • codec 编解码器的 AVCodec
    • width 图像的宽度
    • height 图像的高度
    • pix_fmt 像素格式
    • sample_rate 采样率
    • channels 声道数
    • sample_fmt 采样格式
  • AVCodec

    • id
    • name
    • long_name
    • type
    • 一些编解码的接口函数
  • AVPacket

    • pts:显示时间戳
    • dts :解码时间戳
    • data :压缩编码数据
    • size :压缩编码数据大小
    • stream_index :所属的 AVStream
  • AVFrame

    • pts:显示时间戳
    • dts :解码时间戳
    • data :压缩编码数据
    • size :压缩编码数据大小
    • stream_index :所属的 AVStream
// duration
printf("duraion: %d \n", pFormatCtx->duration);
// bit_rate
printf("bit_rate: %d \n", pFormatCtx->bit_rate);
// long_name
printf("long_name: %s \n", pFormatCtx->iformat->long_name);
// time_base
printf("time_base: %d \n", pFormatCtx->streams[0]->time_base);
// width height
int streamIndex = 1;
for(i = 0; i < pFormatCtx->nb_streams; i++){
  if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){
      streamIndex = i;
      break;
    }
}
printf("width: %d \n", pFormatCtx->streams[0]->codec->width);
printf("height: %d \n", pFormatCtx->streams[0]->codec->height);

输出结果

duraion: 34087000
bit_rate: 219113
long_name: FLV (Flash Video)
time_base: 1
width: 512
height: 288

输出信息到文件

FILE *fp = fopen("info.txt","wb+");
// duration
fprintf(fp, "duraion: %d \n", pFormatCtx->duration);
// bit_rate
fprintf(fp, "bit_rate: %d \n", pFormatCtx->bit_rate);
// long_name
fprintf(fp, "long_name: %s \n", pFormatCtx->iformat->long_name);
// time_base
fprintf(fp, "time_base: %d \n", pFormatCtx->streams[0]->time_base);
// width height
int streamIndex = 1;
for(i = 0; i < pFormatCtx->nb_streams; i++){
  if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){
      streamIndex = i;
      break;
    }
}
fprintf(fp, "width: %d \n", pFormatCtx->streams[0]->codec->width);
fprintf(fp, "height: %d \n", pFormatCtx->streams[0]->codec->height);
fclose(fp);
// fwrite packet
fwrite(packet->data, 1, packet->size, fp_h264);
// fwrite yuv
fwrite(pFrameYUV->data[0], 1, pCodecCtx->width * pCodecCtx->height, fp_yuv);
fwrite(pFrameYUV->data[1], 1, pCodecCtx->width * pCodecCtx->height/4, fp_yuv);
fwrite(pFrameYUV->data[2], 1, pCodecCtx->width * pCodecCtx->height/4, fp_yuv);

# 流媒体

# 常用的传输协议

  • HLS

Http Live Streaming,由 Apple 公司提出的,基于 HTTP 的流媒体网络传输协议。基本原理是将流媒体切成一段一段的视频文件
优点:不同速率自由切换,浏览器 Video 可直接播放
缺点:延迟很大 10s 以上

  • RTMP

Real-Time Message Protocol,由 Adobe 公司提出的流媒体协议,未完全公开,一般传输的是 flv,f4v 格式的视频流,在 TCP 的 1 个通道上传输命令和数据
优点:低延迟,稳定
缺点:私有协议,兼容性差,容易被防火墙阻拦

  • RTSP

Real-Time Stream Protocol 由 Real Neworks 和 Netscape 共同提出的流媒体协议,是共有协议,有专门机构负责维护,RTSP 一般传输的是 TS,mp4 格式的视频流,传输一般需要 2-3 个通道,命令和数据通道分离
优点:实时效果很好
缺点:浏览器不能直接播放

# 推流

# 本地文件转RTMP
ffmpeg -re -i input.mp4 -c copy -f flv  rtmp://localhost:1935/live/filetortmp

# 本地文件切片为hls m3u8

ffmpeg -i input.mp4 -c copy -f segment -segment_list ./hls/live.m3u8 -segment_time 2  ./hls/live%03d.ts

# 本地文件转HLS
ffmpeg  -re -i input.mp4 -c:v h264 -flags +cgop -g 30 -hls_time 1 -hls_flags delete_segments ./hls/live.m3u8

# RTSP转RTMP
ffmpeg -i rtsp://192.168.0.10:554 -f flv rtmp://127.0.0.1:1935/live/rtsptortmps


# RTSP转HLS
ffmpeg -i rtsp://192.168.0.10:554 -c:v h264 -flags +cgop -g 30 -hls_time 1 -hls_flags delete_segments ./hls/live.m3u8
# -c:v h264 指定编解码器
# -flags +cgop

NodeMediaServer

https://github.com/illuspas/Node-Media-Server

# 拉流

ffmpeg -i rtmp://rtmp.gausszhou.top/live

# 播放

hls

  • video 标签直接播放 m3u8 文件 hls
  • flv.js 播放 flv 文件

rtmp

video.js 播放 rtmp 视频流---需要 flash

rtsp

  • VlC 插件将 rtsp 转成 ogg---需要安装浏览器插件
  • RTSP 转 RTMP rtsp-->ffmpeg+nginx+video.js-->rtmp
  • RTSP 转 HLS rtsp-->ffmpeg+video.js-->hls
  • RTSP 转 WebRTC github.com/deepch/RTSPtoWebRTC