# 视频开发入门
# 基本概念
# 容器
视频文件本身是一个容器,里面包含了视频和音频,也可能有字幕等内容 常见的容器格式有以下几种,一般来说,视频文件的后缀名就是它的容器格式
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