FFmpeg解决视频播放加载卡顿问题(FFmpeg+M3U8分片)
在这静谧的时光里,我们能够更清晰地审视自己,思考未来的方向。每一步的坚实,都是对勇气的拥抱,每一个夜晚的努力,都是对未来的信仰。不要害怕独行,因为正是在寂静中,我们更能听见内心深处的声音,更能感受到梦想的脉动。
1.问题回顾
为什么会讨论这个问题呢,原因是我们做了一个在线培训系统,但是存在视频播放卡顿问题,按道理来说,这个是不应该的!因为服务器已经是顶配了,宽带甚至达到了上百,但是很可惜,几个人看视频都会卡顿!而且,这个对象存储还用的是华为云,当然,这里承认一件事,我们没有使用CDN。
这里我们大概介绍一下啥叫做CDN,作为一个拓展,就开始正文:
CDN(Content Delivery Network)是一种用于提高网站性能、可用性和安全性的网络架构。它通过将内容分发到离用户更近的服务器节点,从而减少延迟、提高加载速度,同时能够有效处理大流量和提供安全保障。以下是CDN技术的一些关键特点和组成部分:
1. 关键特点:
-
较低的延迟和更快的加载速度: CDN通过在全球范围内的多个服务器节点分发内容,使用户能够从距离更近的服务器获取数据,从而减少延迟和提高加载速度。
-
更高的可用性和可靠性: CDN通过将内容存储在多个地理位置的服务器上,提高了内容的冗余度,从而增加了系统的可用性和可靠性。
-
减轻源服务器负担: CDN能够缓存并提供静态内容,减轻了源服务器的负载,使其更专注于动态内容的生成。
-
大流量处理能力: CDN分布式的特性允许它有效地处理大量的并发请求,从而保证了高效的内容分发。
-
提供安全性和防护: CDN通常具备一定的安全功能,例如DDoS攻击防护、Web应用程序防火墙(WAF)等,以增强对网站的安全保障。
2. CDN的组成部分:
-
边缘服务器节点: CDN的核心组成部分是分布在全球各地的边缘服务器节点。这些节点存储着静态内容的副本,以便更快地响应用户请求。
-
内容分发服务器(CDN服务器): 负责协调用户请求的CDN服务器,决定从哪个边缘节点提供服务,并负责内容的分发和管理。
-
负载均衡器: 用于平衡用户请求的负载,确保每个边缘节点都得到合理的请求分发。
-
缓存: 用于存储和管理缓存的组件,以便在需要时能够快速提供内容。
-
安全功能: 包括DDoS防护、SSL加密、WAF等安全措施,以保护网站免受恶意攻击。
-
分发协议: 用于确定如何将内容传递到用户的协议,常见的包括HTTP、HTTPS、以及最近的HTTP/2和HTTP/3。
3. CDN的工作原理:
-
DNS解析: 用户发起请求时,通过DNS解析获得最近的CDN边缘节点的IP地址。
-
请求路由: CDN服务器根据负载均衡策略,将用户请求路由到最合适的边缘节点。
-
内容缓存: 边缘节点检查是否有所请求内容的缓存。如果存在,直接返回缓存内容,否则向源服务器请求并缓存内容。
-
内容返回: 边缘节点将请求的内容返回给用户,完成请求-响应过程。
CDN技术在提高网站性能、可用性和安全性方面发挥了重要作用,特别是在大规模内容分发的场景中,CDN的应用变得尤为关键。
2.技术解决
1.产品介绍
在经过大量的百度学习,我们发现一款开源大作:FFmpeg。对,就是这个神器!此物不仅仅说是应用于我们编程圈,再音视频多媒体圈也是颇具盛名!
FFmpeg(Fast Forward MPEG)是一个开源的多媒体处理工具集,它包含了音频和视频处理库、编码器、解码器、转码器等多种工具。以下是FFmpeg的主要功能介绍:
- 音视频编解码(Codec):
- FFmpeg支持各种音频和视频编解码器,包括常见的H.264、H.265、AAC、MP3等,使其能够处理各种媒体格式。
- 格式转换:
- 可以将不同格式的音频和视频文件相互转换,例如将MP4转换为AVI、将WAV转换为MP3等。
- 流媒体处理:
- FFmpeg支持从网络摄像头、文件、或其他来源捕获音视频流,也能将处理后的流推送到服务器或其他设备。
- 图像处理:
- FFmpeg不仅仅可以处理音视频,还支持图像处理,如提取视频帧,合成图片和视频等。
- 剪辑和编辑:
- 可以对音视频进行剪辑和编辑,包括裁剪、剪切、拼接等操作。
- 字幕处理:
- 支持字幕的添加、移除和编辑,可以将字幕嵌入到视频中或者从视频中提取字幕。
- 音频处理:
- 提供了丰富的音频处理功能,包括音频的剪辑、混音、音量调节等。
- 实时视频处理:
- FFmpeg能够处理实时的音视频流,适用于直播、视频会议等场景。
- 滤镜和效果:
- 支持各种滤镜和效果,如模糊、旋转、调整亮度、对比度等。
FFmpeg的强大功能使其成为许多多媒体应用和服务的核心组件,例如视频编辑软件、流媒体服务器、嵌入式设备等。由于其广泛的支持和社区贡献,FFmpeg已经成为处理多媒体数据的重要工具之一。
由于我们的业务逻辑涉及到流媒体,那么,我们就把关注点放在流媒体处理!打蛇打七寸,我们着重下手!
2.流媒体处理
流媒体处理是一种通过网络实时传输音频和视频数据的技术,允许用户在数据传输的同时观看或听取内容,而不需要等待完整的文件下载。FFmpeg是一个强大的工具,广泛用于流媒体处理。以下是流媒体处理的主要方面以及FFmpeg在这些方面的应用:
- 流媒体捕获:
- FFmpeg可以从各种来源捕获音频和视频流,包括摄像头、麦克风、文件、URL等。通过使用FFmpeg的输入模块,用户可以轻松地实现从这些源中捕获多媒体数据。
# 从摄像头捕获视频
ffmpeg -f v4l2 -i /dev/video0 output.mp4# 从麦克风捕获音频
ffmpeg -f alsa -i hw:0 output.wav# 从URL捕获网络流
ffmpeg -i http://example.com/stream.m3u8 output.mp4
- 流媒体转码:
- 在流媒体处理中,有时需要将音视频数据转码为特定格式或编码,以适应不同的设备或网络条件。FFmpeg提供了广泛的编码器和解码器支持,使得转码变得简单。
# 将输入流转码为H.264视频和AAC音频
ffmpeg -i input.mp4 -c:v libx264 -c:a aac output.mp4
- 流媒体推送:
- FFmpeg可以将处理后的音视频流推送到流媒体服务器,以便在网络上进行分发。这对于实时直播和视频会议非常有用。
# 推送到RTMP服务器
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -f flv rtmp://example.com/live/stream
- 实时流媒体处理:
- FFmpeg支持实时处理音视频流,适用于需要低延迟的应用,如实时直播和视频通话。
# 实时捕获摄像头并推送到RTMP服务器
ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -c:a aac -f flv rtmp://example.com/live/stream
- 流媒体过滤器:
- FFmpeg提供了丰富的过滤器,可以对音视频流进行各种处理,如添加水印、调整亮度、旋转、裁剪等。
# 在视频上添加水印
ffmpeg -i input.mp4 -i watermark.png -filter_complex overlay=10:10 output.mp4
- 自适应比特率:
- FFmpeg可以实现自适应比特率(Adaptive Bitrate Streaming,ABR),以根据用户的网络条件自动调整流的质量。
# 使用多个输出流实现自适应比特率
ffmpeg -i input.mp4 -c:v libx264 -b:v 2000k -c:a aac -b:a 128k -f hls -hls_time 4 -hls_playlist_type vod output.m3u8
上述示例展示了一些FFmpeg在流媒体处理中的常见用法。这些功能使FFmpeg成为流媒体处理的强大工具,适用于多种场景,包括在线直播、视频会议、实时通信等。
3.问题深入
由于我也是IT小学生,这里我简单说一下对于视频播放卡顿我的个人理解:
作为项目的参与者,我们是使用了华为云的对象存储,但是,在视频的播放的时候,我们并没有学习人家其他网站一样,使用m3u8格式进行分片传输,而是一股脑的直接把视频地址抛给前端,自己加载播放,这样子呢,如果大量请求,肯定存在卡顿现象。所以,要么转码,要么分片分批次
视频转码是将一个视频文件从一种编码或格式转换为另一种编码或格式的过程。这过程的目的是为了满足不同终端设备、网络环境或应用场景的需求,以提高视频的兼容性、播放效果、传输效率和存储效率。视频转码有以下一些主要作用:
-
兼容性提升: 不同的终端设备和播放器对视频格式和编码的支持有所差异。通过转码,可以将视频转换为广泛支持的格式,确保在各种设备和平台上都能正常播放。
-
播放效果优化: 转码可以改变视频的分辨率、比特率、帧率等参数,以适应不同的播放环境。例如,在移动设备上,可以将视频分辨率调整为适应小屏幕,以提高观看体验。
-
网络传输效率提高: 不同的网络环境对视频传输的带宽要求不同。通过调整视频的压缩率,可以降低视频文件的大小,提高在低带宽环境下的传输效率。
-
存储空间节省: 对于大型视频平台或存储服务提供商来说,原始视频文件可能占用大量存储空间。通过转码,可以将视频文件压缩成更小的文件,从而降低存储成本。
-
支持多码率自适应流: 多码率自适应流(Adaptive Bitrate Streaming,ABR)是一种通过提供不同比特率的视频流,以适应用户网络带宽的技术。转码可以生成多个不同比特率的视频流,以支持ABR,从而在播放时能够根据用户的网络情况动态切换清晰度。
-
格式转换: 转码可以将视频从一种格式转换为另一种格式,例如从AVI到MP4、从MKV到WebM等。这有助于确保视频在不同平台和设备上的兼容性。
M3U8是一种用于指定多媒体播放列表的格式,常用于流媒体协议中,特别是用于HTTP Live Streaming(HLS)协议。HLS通过将整个视频分成一系列小的、独立的.ts文件(Transport Stream),并使用M3U8播放列表来指导播放器在不同比特率和分辨率之间切换,以实现自适应流媒体传输。以下是M3U8分片的基本工作原理:
-
切片生成: 视频文件首先被切分成一系列小的.ts文件,每个文件包含视频的一小部分内容。这些切片通常有相同的持续时间,例如2秒或10秒。
-
M3U8播放列表生成: 为了指导播放器正确地按顺序播放这些切片,一个M3U8播放列表文件被创建。该文件包含了所有切片的信息,包括其相对路径、时长、序号等。在M3U8文件中,包括了不同清晰度(多码率自适应流)的版本,以便播放器可以根据网络条件选择最合适的版本。
-
播放器请求和播放: 播放器通过HTTP请求M3U8文件,并解析其中的信息。然后,它根据M3U8文件中的信息逐个请求切片文件,并按顺序播放这些切片。
这个过程的优势在于,它允许根据用户的网络状况和设备性能自适应地调整视频质量。如果用户的网络速度较慢,播放器可以选择较低分辨率和比特率的切片,以确保连续的播放。如果网络条件改善,播放器可以选择更高质量的切片,提供更清晰的画面。
4.问题解决
使用FFmpeg来实现M3U8分片,通常需要进行两个主要步骤:首先是将原始视频文件切分成一系列小的.ts文件,然后是生成一个包含这些切片信息的M3U8播放列表。以下是一个简单的示例:
步骤1:切片生成
使用以下命令将原始视频文件切分成.ts文件:
ffmpeg -i input_video.mp4 -c copy -bsf:v h264_mp4toannexb -f segment -segment_time 10 -segment_list output_playlist.m3u8 -segment_format mpegts output_%03d.ts
-i input_video.mp4
:指定输入视频文件。-c copy
:保持视频和音频的原始编码。-bsf:v h264_mp4toannexb
:将H.264编码的视频转换为MPEG-TS格式。-f segment
:指定输出格式为segment。-segment_time 10
:每个切片的时长,这里设置为10秒。-segment_list output_playlist.m3u8
:指定M3U8播放列表的文件名。-segment_format mpegts
:指定切片的格式为MPEG-TS。output_%03d.ts
:输出切片的文件名模板,%03d
表示三位数的序号。
步骤2:生成M3U8播放列表
使用以下命令生成M3U8播放列表:
ffmpeg -f concat -safe 0 -i output_playlist.m3u8 -c copy -bsf:a aac_adtstoasc output_final.m3u8
-f concat
:指定输入文件格式为concat。-safe 0
:允许使用相对路径。-i output_playlist.m3u8
:指定输入M3U8播放列表文件。-c copy
:保持原始编码。-bsf:a aac_adtstoasc
:将AAC音频流的ADTS头转换为MPEG-4 Audio(asc)格式。
最终,output_final.m3u8
将包含所有切片信息,可以被用作HLS流的播放列表。
请注意,这只是一个简单的示例,实际应用中可能需要更多的参数配置,例如视频编码选项、分辨率、比特率等,以满足特定需求。此外,FFmpeg的命令行参数可能会根据不同的版本有所变化,请根据您使用的版本查阅相关文档。
3.代码实现
使用Java代码调用FFmpeg库以完成M3U8分片的操作可以使用Java的ProcessBuilder
类。以下是一个简单的Java代码示例,用于调用FFmpeg执行上述步骤:
import java.io.IOException;public class FFmpegHLSProcessor {public static void main(String[] args) {String inputVideoPath = "input_video.mp4";String outputPlaylistPath = "output_playlist.m3u8";String outputFinalPath = "output_final.m3u8";// Step 1: 切片生成try {ProcessBuilder processBuilder = new ProcessBuilder("ffmpeg", "-i", inputVideoPath,"-c", "copy", "-bsf:v", "h264_mp4toannexb","-f", "segment", "-segment_time", "10","-segment_list", outputPlaylistPath,"-segment_format", "mpegts","output_%03d.ts");processBuilder.redirectErrorStream(true);Process process = processBuilder.start();process.waitFor();} catch (IOException | InterruptedException e) {e.printStackTrace();}// Step 2: 生成M3U8播放列表try {ProcessBuilder processBuilder = new ProcessBuilder("ffmpeg", "-f", "concat", "-safe", "0", "-i", outputPlaylistPath,"-c", "copy", "-bsf:a", "aac_adtstoasc",outputFinalPath);processBuilder.redirectErrorStream(true);Process process = processBuilder.start();process.waitFor();} catch (IOException | InterruptedException e) {e.printStackTrace();}}
}
请确保系统上已经安装了FFmpeg,并且Java应用程序可以调用它。
4.总结
大概得解决思路如上,当然,FFmpeg是免费的,CDN是增值服务,各有优劣!
对于FFmpeg+M3U8实现的分片技术,实际生产中肯定还会涉及到复杂的业务逻辑,更具具体情况请多加揣测。
拜拜,我要设计业务逻辑去了!