本地文件->RTSP->HLS->网页播放
流媒体服务器mediamtx
MediaMTX(前身为 rtsp-simple-server)是一款即用型、零依赖的实时媒体服务器和媒体代理。它被设计为一个“媒体路由器”,能够接收、代理、录制、转换和播放多种格式的视频和音频流,支持丰富的流媒体协议,适用于直播、监控、视频会议等多种场景,特性如下:
安装与部署:
1、从其 GitHub 发布页或官网获取预编译的二进制文件直接运行
2、使用 Docker 镜像:docker run --rm -it --network=host bluenviron/mediamtx:latest
以Windows为例下载mediamtx_v1.14.0_windows_amd64.zip,解压后执行mediamtx.exe
使用ffmpeg推流
FFmpeg 是一款功能强大且非常流行的开源多媒体处理框架,被誉为音视频领域的“瑞士军刀” 🔧。它支持海量的音视频格式和编解码器,提供了录制、转换、流化、编辑、播放等全方位的音视频处理能力。示例如下:
查看媒体信息:
ffprobe -i input.mp4转换视频格式(将 MP4 转换为 AVI):
ffmpeg -i input.mp4 output.avi提取视频中的音频:
ffmpeg -i input_video.mp4 -vn output_audio.mp3调整视频分辨率(缩放到 1280x720):
ffmpeg -i input.mp4 -vf scale=1280:720 output.mp4裁剪视频(从第 10 秒开始,截取 30 秒的内容):
ffmpeg -i input.mp4 -ss 00:00:10 -t 00:00:30 output_clip.mp4
ffmpeg推流到mediamtx
这里将MP4文件推到mediamtx,在命令行窗口执行如下命令
ffmpeg -re -stream_loop -1 -i test.mp4 -c copy -f rtsp rtsp://192.168.2.1:8554/rtsp1
此时可以用VLC media player工具直接播放生成的rtsp流地址
ffmpeg推rtsp到本地m3u8文件
ffmpeg -fflags nobuffer -loglevel error -rtsp_transport tcp -i rtsp://192.168.2.1:8554/rtsp1 -vsync 0 -copyts -vcodec copy -movflags frag_keyframe+empty_moov -an -hls_flags delete_segments+append_list -f hls -hls_time 1 -hls_list_size 10 -hls_segment_type mpegts -hls_segment_filename %d.ts index.m3u8
命令解释如下:
ffmpeg
-fflags nobuffer # 减少输入缓冲,降低延迟
-loglevel error # 只显示错误日志,减少输出干扰
-rtsp_transport tcp # 强制使用 TCP 传输 RTSP 流(提高稳定性)
-i rtsp://192.168.2.1:8554/rtsp1 # 输入源:RTSP 流地址
-vsync 0 # 禁用帧率同步,避免重复或丢弃帧
-copyts # 保留原始时间戳(对直播流同步至关重要)
-vcodec copy # 直接复制视频流,不重新编码(节省资源,零延迟)
-an # 丢弃音频流(不处理音频)
-movflags frag_keyframe+empty_moov # 关键帧分片 + 初始 moov 置空(HLS 兼容性)
-f hls # 指定输出格式为 HLS
-hls_flags delete_segments+append_list # 自动删除旧分片 + 动态更新播放列表
-hls_time 1 # 每个 TS 分片时长约 1 秒(降低延迟)
-hls_list_size 10 # 播放列表保留最近 10 个分片
-hls_segment_type mpegts # TS 分片格式(标准 HLS 格式)
-hls_segment_filename %d.ts # 分片文件名格式(数字递增:1.ts, 2.ts...)
index.m3u8 # 输出 HLS 主播放列表文件名
服务器上生成的目录文件如下:
[root@host 01]# ll
总用量 5620
-rw-r--r-- 1 root root 514556 9月 16 16:38 950.ts
-rw-r--r-- 1 root root 504028 9月 16 16:38 951.ts
-rw-r--r-- 1 root root 485792 9月 16 16:38 952.ts
-rw-r--r-- 1 root root 517564 9月 16 16:39 953.ts
-rw-r--r-- 1 root root 500832 9月 16 16:39 954.ts
-rw-r--r-- 1 root root 501584 9月 16 16:39 955.ts
-rw-r--r-- 1 root root 497448 9月 16 16:39 956.ts
-rw-r--r-- 1 root root 493124 9月 16 16:39 957.ts
-rw-r--r-- 1 root root 484664 9月 16 16:39 958.ts
-rw-r--r-- 1 root root 481844 9月 16 16:39 959.ts
-rw-r--r-- 1 root root 479400 9月 16 16:39 960.ts
-rw-r--r-- 1 root root 262144 9月 16 16:39 961.ts
-rw-r--r-- 1 root root 325 9月 16 16:39 index.m3u8
nginx配置
location /hls/ {alias /opt/public/nginx/html/hls/;index index.html index.htm;add_header Cross-Origin-Embedder-Policy 'require-corp';add_header Cross-Origin-Opener-Policy 'same-origin';add_header Cross-Origin-Resource-Policy 'cross-origin';}
服务器播放m3u8文件
将以下文件放到nginx服务器,就可以直接播放生成的m3u8文件
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>M3U8视频播放器</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}body {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;color: #fff;min-height: 100vh;padding: 20px;}.container {max-width: 1200px;margin: 0 auto;padding: 20px;}header {text-align: center;margin-bottom: 30px;padding: 20px;background: rgba(0, 0, 0, 0.3);border-radius: 15px;box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);}h1 {font-size: 2.5rem;margin-bottom: 10px;text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);}.subtitle {font-size: 1.2rem;opacity: 0.9;}.player-container {background: rgba(0, 0, 0, 0.5);border-radius: 15px;overflow: hidden;box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);margin-bottom: 30px;}#video-player {width: 100%;height: 500px;background: #000;}.controls {display: flex;flex-wrap: wrap;gap: 15px;padding: 20px;background: rgba(0, 0, 0, 0.4);}.input-group {flex: 1;min-width: 300px;}label {display: block;margin-bottom: 8px;font-weight: 500;}input[type="text"] {width: 100%;padding: 12px 15px;border: none;border-radius: 8px;background: rgba(255, 255, 255, 0.1);color: white;font-size: 1rem;}input[type="text"]:focus {outline: none;background: rgba(255, 255, 255, 0.2);}button {background: #ff5722;color: white;border: none;padding: 12px 25px;border-radius: 8px;cursor: pointer;font-size: 1rem;font-weight: 600;transition: all 0.3s ease;box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);}button:hover {background: #ff7043;transform: translateY(-2px);box-shadow: 0 6px 15px rgba(0, 0, 0, 0.4);}.info-panel {background: rgba(0, 0, 0, 0.4);border-radius: 15px;padding: 25px;margin-top: 30px;}.info-panel h2 {margin-bottom: 20px;font-size: 1.8rem;color: #ff9800;}.features {display: grid;grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));gap: 20px;margin-top: 20px;}.feature {background: rgba(255, 255, 255, 0.1);padding: 20px;border-radius: 10px;transition: transform 0.3s ease;}.feature:hover {transform: translateY(-5px);background: rgba(255, 255, 255, 0.15);}.feature h3 {color: #4fc3f7;margin-bottom: 10px;font-size: 1.3rem;}footer {text-align: center;margin-top: 40px;padding: 20px;font-size: 0.9rem;opacity: 0.8;}@media (max-width: 768px) {#video-player {height: 300px;}h1 {font-size: 2rem;}}</style>
</head>
<body><div class="container"><header><h1>M3U8视频播放器</h1><p class="subtitle">直接在浏览器中播放HLS流媒体</p></header><div class="player-container"><video id="video-player" controls></video><div class="controls"><div class="input-group"><label for="m3u8-url">M3U8文件URL:</label><input type="text" id="m3u8-url" placeholder="01/index.m3u8" value="01/index.m3u8"></div><button id="play-btn">播放视频</button></div></div><div class="info-panel"><h2>关于HLS和M3U8</h2><p>HLS(HTTP Live Streaming)是苹果公司开发的流媒体传输协议,M3U8是其播放列表文件格式。本播放器使用hls.js库在浏览器中实现HLS播放功能。</p><div class="features"><div class="feature"><h3>跨浏览器支持</h3><p>支持Chrome、Firefox、Safari、Edge等主流浏览器,无需任何插件。</p></div><div class="feature"><h3>自适应码率</h3><p>自动根据网络状况选择最佳视频质量,提供流畅的观看体验。</p></div><div class="feature"><h3>实时流支持</h3><p>支持直播流媒体播放,延迟低至几秒钟。</p></div></div></div><footer><p>© 2023 M3U8视频播放器 | 基于hls.js技术实现</p></footer></div><!-- 引入hls.js库 --><script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script><script>document.addEventListener('DOMContentLoaded', function() {const videoPlayer = document.getElementById('video-player');const m3u8UrlInput = document.getElementById('m3u8-url');const playButton = document.getElementById('play-btn');// 初始化播放器function initPlayer() {const url = m3u8UrlInput.value.trim();if (!url) {alert('请输入有效的M3U8 URL');return;}// 清除之前的播放器实例if (window.hls) {window.hls.destroy();}// 检查浏览器是否原生支持HLSif (videoPlayer.canPlayType('application/vnd.apple.mpegurl')) {// Safari原生支持HLSvideoPlayer.src = url;videoPlayer.play();} else if (Hls.isSupported()) {// 使用hls.js支持其他浏览器window.hls = new Hls();window.hls.loadSource(url);window.hls.attachMedia(videoPlayer);window.hls.on(Hls.Events.MANIFEST_PARSED, function() {videoPlayer.play();});// 错误处理window.hls.on(Hls.Events.ERROR, function(event, data) {console.error('HLS Error:', data);if (data.fatal) {switch(data.type) {case Hls.ErrorTypes.NETWORK_ERROR:alert('网络错误: 无法加载视频资源');break;case Hls.ErrorTypes.MEDIA_ERROR:alert('媒体错误: 无法解码视频');break;default:alert('播放错误: 请检查URL或尝试刷新页面');break;}}});} else {alert('您的浏览器不支持HLS播放');}}// 播放按钮事件playButton.addEventListener('click', initPlayer);// 输入框回车事件m3u8UrlInput.addEventListener('keypress', function(e) {if (e.key === 'Enter') {initPlayer();}});// 初始化示例视频setTimeout(initPlayer, 1000);});</script>
</body>
</html>