
以下完整的流媒体搭建、推流和前端播放方案支持HTTP-FLV和WebSocket协议。一、整体架构视频文件 → FFmpeg推流(循环推送) → Nginxnginx-http-flv-module流媒体服务器 → Vue前端(flv.js播放)二、流媒体服务器搭建详细步骤1. 依赖库安装# CentOS/RHEL系列 sudo yum install -y gcc gcc-c pcre pcre-devel zlib zlib-devel openssl openssl-devel # Ubuntu/Debian系列 sudo apt-get update sudo apt-get install -y build-essential libpcre3 libpcre3-dev zlib1g-dev libssl-dev2. 下载Nginx和nginx-http-flv-module# 创建并进入工作目录 mkdir -p /opt/streaming cd /opt/streaming # 下载nginx-1.24.0或其他稳定版本 wget http://nginx.org/download/nginx-1.24.0.tar.gz tar -zxvf nginx-1.24.0.tar.gz # 下载nginx-http-flv-module已包含nginx-rtmp-module所有功能 wget https://github.com/winshining/nginx-http-flv-module/archive/refs/tags/v1.2.12.tar.gz tar -zxvf v1.2.12.tar.gz # 或者使用git克隆 # git clone https://github.com/winshining/nginx-http-flv-module.git3. 编译Nginx并加载模块cd nginx-1.24.0 # 配置编译参数添加http-flv模块 ./configure \ --prefix/usr/local/nginx \ --with-http_ssl_module \ --with-http_flv_module \ --add-module../nginx-http-flv-module-1.2.12 # 编译并安装 make -j$(nproc) sudo make install4. 验证模块是否安装成功sudo /usr/local/nginx/sbin/nginx -V # 在输出中应该能看到--add-module../nginx-http-flv-module-1.2.125. 配置Nginx完整配置示例编辑Nginx配置文件sudo vim /usr/local/nginx/conf/nginx.conf完整配置内容如下#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } # RTMP配置用于接收推流 rtmp { out_queue 4096; out_cork 8; max_streams 128; timeout 15s; drop_idle_publisher 15s; log_interval 5s; # 日志记录间隔 log_size 1m; # 日志缓冲区大小 server { listen 1935; # RTMP监听端口 chunk_size 4096; application live { # 直播应用 live on; record off; gop_cache on; # 开启GOP缓存降低延迟 # 允许跨域推流 allow publish all; allow play all; } application hls { # HLS应用可选 live on; hls on; hls_path /usr/local/nginx/html/hls; hls_fragment 5s; hls_playlist_length 30s; } } } # HTTP配置用于HTTP-FLV分发 http { include mime.types; default_type application/octet-stream; #log_format main $remote_addr - $remote_user [$time_local] $request # $status $body_bytes_sent $http_referer # $http_user_agent $http_x_forwarded_for; #access_log logs/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; server { listen 8080; # HTTP监听端口 server_name localhost; # 跨域配置 add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Credentials true; add_header Access-Control-Allow-Methods GET, POST, OPTIONS; add_header Access-Control-Allow-Headers DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } # HTTP-FLV拉流配置核心 location /live { flv_live on; # 开启HTTP-FLV直播 chunked_transfer_encoding on; # 支持分块传输编码 add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Credentials true; } # HLS播放配置可选 location /hls { types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } root /usr/local/nginx/html; add_header Cache-Control no-cache; add_header Access-Control-Allow-Origin *; } # 统计信息 location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } location /stat.xsl { root /usr/local/nginx-http-flv-module-1.2.12; # 指定stat.xsl位置 } # 控制接口可选 location /control { rtmp_control all; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location /50x.html { root html; } } }6. 启动Nginx服务# 启动Nginx sudo /usr/local/nginx/sbin/nginx # 检查启动状态 ps aux | grep nginx # 如果修改配置后重载 sudo /usr/local/nginx/sbin/nginx -s reload # 停止Nginx sudo /usr/local/nginx/sbin/nginx -s stop三、从视频文件循环推流1. 安装FFmpeg# CentOS/RHEL sudo yum install -y epel-release sudo yum install -y ffmpeg ffmpeg-devel # Ubuntu/Debian sudo apt-get install -y ffmpeg2. 循环推流命令# 基本推流命令循环推送本地视频文件 ffmpeg -re -stream_loop -1 -i /path/to/your/video.mp4 -c copy -f flv rtmp://127.0.0.1:1935/live/stream # 参数说明 # -re以原始帧率读取输入模拟实时 # -stream_loop -1无限循环 # -i输入文件路径 # -c copy直接复制编码不重新编码性能更好 # -f flv输出格式为FLV # rtmp://...推流地址 # 如果需要重新编码并调整参数推荐用于不同格式的视频 ffmpeg -re -stream_loop -1 -i /path/to/video.mp4 \ -c:v libx264 -preset ultrafast -tune zerolatency \ -b:v 1000k -maxrate 2000k \ -c:a aac -b:a 128k -ar 44100 -ac 2 \ -f flv rtmp://127.0.0.1:1935/live/stream # 从USB摄像头推流实际场景 ffmpeg -f v4l2 -framerate 10 -i /dev/video0 -q 10 -f flv rtmp://127.0.0.1:1935/live/stream3. 创建自动推流脚本推荐创建一个脚本文件push_stream.sh#!/bin/bash # 配置 VIDEO_PATH/path/to/your/video.mp4 RTMP_URLrtmp://127.0.0.1:1935/live/stream LOG_FILE/var/log/push_stream.log # 检查视频文件是否存在 if [ ! -f $VIDEO_PATH ]; then echo Error: Video file not found: $VIDEO_PATH exit 1 fi # 循环推流 while true; do echo [$(date)] Starting push stream... $LOG_FILE ffmpeg -re -stream_loop 1 -i $VIDEO_PATH \ -c:v libx264 -preset ultrafast -tune zerolatency \ -b:v 1000k \ -c:a aac -b:a 128k \ -f flv $RTMP_URL \ -loglevel error \ $LOG_FILE 21 if [ $? -ne 0 ]; then echo [$(date)] Push stream failed, retrying in 5 seconds... $LOG_FILE sleep 5 fi done设置脚本权限并运行chmod x push_stream.sh nohup ./push_stream.sh 四、播放验证方式1. 使用VLC播放器验证打开VLC → 媒体 → 打开网络串流输入以下地址RTMP地址rtmp://服务器IP:1935/live/streamHTTP-FLV地址http://服务器IP:8080/live?port1935applivestreamstream2. 使用FFplay命令行验证# 验证RTMP流 ffplay rtmp://127.0.0.1:1935/live/stream # 验证HTTP-FLV流 ffplay http://127.0.0.1:8080/live?port1935applivestreamstream3. 使用浏览器验证直接访问http://服务器IP:8080/stat查看推流统计信息。五、Vue前端可直接调试代码1. 创建Vue项目并安装依赖# 创建Vue项目如已有项目可跳过 vue create live-player # 安装flv.js npm install flv.js --save # 或使用yarn yarn add flv.js2. 完整Vue组件代码template div classlive-player-container h1直播播放器/h1 !-- 配置区域 -- div classconfig-section div classform-group label协议类型/label select v-modelprotocol option valuehttp-flvHTTP-FLV/option option valuewebsocketWebSocket/option /select /div div classform-group label播放地址/label input v-modelstreamUrl placeholder请输入流地址 classurl-input / /div div classform-group button clickstartPlay :disabledisPlaying classbtn-primary {{ isPlaying ? 播放中... : 开始播放 }} /button button clickstopPlay :disabled!isPlaying classbtn-danger 停止播放 /button /div /div !-- 视频播放区域 -- div classvideo-section video refvideoElement classvideo-player controls muted autoplay /video /div !-- 状态信息 -- div classstatus-section v-ifstatusMessage div :class[status-message, statusType] {{ statusMessage }} /div /div !-- 预设地址方便调试 -- div classpreset-section h3快速选择地址请根据实际IP修改/h3 div classpreset-buttons button v-for(url, index) in presetUrls :keyindex clickselectPreset(url) classbtn-preset {{ url.name }} /button /div /div /div /template script import flvjs from flv.js export default { name: LivePlayer, data() { return { protocol: http-flv, streamUrl: http://192.168.1.100:8080/live?port1935applivestreamstream, isPlaying: false, flvPlayer: null, statusMessage: , statusType: info, presetUrls: [ { name: 本地测试-HTTP-FLV, url: http://localhost:8080/live?port1935applivestreamstream }, { name: 本机IP-HTTP-FLV, url: http://${window.location.hostname || 192.168.1.100}:8080/live?port1935applivestreamstream }, { name: RTMP地址参考, url: rtmp://192.168.1.100:1935/live/stream } ] } }, methods: { // 选择预设地址 selectPreset(preset) { this.streamUrl preset.url if (this.isPlaying) { this.stopPlay() } }, // 构建播放配置 buildMediaDataSource(url) { if (this.protocol http-flv) { return { type: flv, isLive: true, url: url } } else if (this.protocol websocket) { // WebSocket模式需要后端支持这里给出示例 return { type: flv, isLive: true, url: url.replace(http://, ws://) // 简单转换示例 } } }, // 开始播放 startPlay() { if (!this.streamUrl) { this.showStatus(请输入播放地址, error) return } // 检查flv.js是否支持 if (!flvjs.isSupported()) { this.showStatus(您的浏览器不支持FLV播放, error) return } // 停止当前播放 this.stopPlay() try { const videoElement this.$refs.videoElement const mediaDataSource this.buildMediaDataSource(this.streamUrl) // 创建播放器实例 this.flvPlayer flvjs.createPlayer(mediaDataSource, { enableWorker: false, // 不使用Worker降低延迟 enableStashBuffer: false, // 关闭缓存降低延迟 stashInitialSize: 1, // 初始缓存大小 lazyLoad: false, // 关闭懒加载 lazyLoadMaxDuration: 1, // 懒加载最大时长 lazyLoadRecoverDuration: 1, // 懒加载恢复时长 deferLoadAfterSourceOpen: false, autoCleanupMaxBackwardDuration: 1, autoCleanupMinBackwardDuration: 1, statisticsInfoReportInterval: 1000, // 统计信息上报间隔 fixAudioTimestampGap: false, accurateSeek: false, seekType: range, reuseRedirectedURL: true }) // 绑定视频元素 this.flvPlayer.attachMediaElement(videoElement) // 注册事件监听 this.flvPlayer.on(flvjs.Events.ERROR, (errorType, errorDetail) { console.error(FLV Error:, errorType, errorDetail) this.showStatus(播放错误: ${errorDetail}, error) this.isPlaying false }) this.flvPlayer.on(flvjs.Events.LOADING_COMPLETE, () { console.log(加载完成) }) this.flvPlayer.on(flvjs.Events.RECOVERED_EARLY_EOF, () { console.log(恢复播放) }) this.flvPlayer.on(flvjs.Events.MEDIA_INFO, (mediaInfo) { console.log(媒体信息:, mediaInfo) }) this.flvPlayer.on(flvjs.Events.METADATA_ARRIVED, (metadata) { console.log(metadata:, metadata) }) this.flvPlayer.on(flvjs.Events.STATISTICS_INFO, (stats) { // 可以显示实时统计信息 console.log(当前解码帧数:, stats.decodedFrames) }) // 加载并播放 this.flvPlayer.load() this.flvPlayer.play() this.isPlaying true this.showStatus(正在播放..., success) } catch (error) { console.error(创建播放器失败:, error) this.showStatus(创建播放器失败: ${error.message}, error) this.isPlaying false } }, // 停止播放 stopPlay() { if (this.flvPlayer) { try { this.flvPlayer.pause() this.flvPlayer.unload() this.flvPlayer.detachMediaElement() this.flvPlayer.destroy() } catch (e) { console.error(停止播放错误:, e) } this.flvPlayer null } // 清除视频元素 const videoElement this.$refs.videoElement if (videoElement) { videoElement.src videoElement.load() } this.isPlaying false this.showStatus(已停止播放, info) }, // 显示状态信息 showStatus(message, type) { this.statusMessage message this.statusType type || info // 5秒后自动清除状态 setTimeout(() { if (this.statusMessage message) { this.statusMessage } }, 5000) } }, // 组件销毁时清理 beforeDestroy() { this.stopPlay() } } /script style scoped .live-player-container { max-width: 1200px; margin: 0 auto; padding: 20px; font-family: Segoe UI, Tahoma, Geneva, Verdana, sans-serif; } h1 { text-align: center; color: #333; margin-bottom: 30px; } .config-section { background: #f5f5f5; padding: 20px; border-radius: 8px; margin-bottom: 20px; } .form-group { margin-bottom: 15px; display: flex; align-items: center; gap: 10px; } .form-group label { min-width: 80px; font-weight: bold; color: #555; } select, .url-input { flex: 1; padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; } .url-input { min-width: 300px; } .btn-primary, .btn-danger, .btn-preset { padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; font-weight: bold; transition: all 0.3s; } .btn-primary { background: #1890ff; color: white; } .btn-primary:hover:not(:disabled) { background: #40a9ff; } .btn-danger { background: #ff4d4f; color: white; } .btn-danger:hover:not(:disabled) { background: #ff7875; } .btn-primary:disabled, .btn-danger:disabled { opacity: 0.6; cursor: not-allowed; } .video-section { background: #000; border-radius: 8px; overflow: hidden; margin-bottom: 20px; } .video-player { width: 100%; max-height: 500px; display: block; } .status-section { margin-bottom: 20px; } .status-message { padding: 10px 15px; border-radius: 4px; font-size: 14px; } .status-message.info { background: #e6f7ff; border: 1px solid #91d5ff; color: #1890ff; } .status-message.success { background: #f6ffed; border: 1px solid #b7eb8f; color: #52c41a; } .status-message.error { background: #fff2f0; border: 1px solid #ffccc7; color: #ff4d4f; } .preset-section { background: #f9f9f9; padding: 20px; border-radius: 8px; } .preset-section h3 { margin: 0 0 15px 0; color: #555; } .preset-buttons { display: flex; gap: 10px; flex-wrap: wrap; } .btn-preset { background: white; color: #1890ff; border: 1px solid #1890ff; } .btn-preset:hover { background: #e6f7ff; } /style3. 在Vue项目中使用该组件template div idapp LivePlayer / /div /template script import LivePlayer from ./components/LivePlayer.vue export default { name: App, components: { LivePlayer } } /script六、WebSocket播放支持说明对于WebSocket协议的支持需要在服务端增加WebSocket代理。您可以使用以下方案使用Node.js搭建WebSocket转发服务接收RTMP/HTTP-FLV流通过WebSocket转发给前端使用SRS流媒体服务器的WebSocket支持SRS原生支持WebSocket播放FLV前端WebSocket播放需要服务端支持// 当协议选择为WebSocket时构建不同的MediaDataSource const wsDataSource { type: flv, isLive: true, url: ws://your-server:8888/live/stream // WebSocket地址 }七、常见问题排查1. 推流失败检查Nginx是否启动ps aux | grep nginx检查端口是否开放netstat -an | grep 1935检查防火墙sudo firewall-cmd --list-all或sudo ufw status2. 播放黑屏检查视频文件编码格式推荐使用H.264编码在浏览器控制台查看错误信息尝试使用VLC验证流是否正常3. 跨域问题已在Nginx配置中添加跨域头如果仍有问题检查浏览器控制台是否有CORS错误。4. 延迟过大调整flv.js配置参数{ enableStashBuffer: false, stashInitialSize: 1, lazyLoad: false }执行后台命令nohup ffmpeg -re -stream_loop -1 -i /path/to/your/video.mp4 -c:v libx264 -preset veryfast -crf 28 -b:v 500k -maxrate 500k -bufsize 1000k -c:a aac -b:a 64k -f flv rtmp://47.120.15.75:1935/live/stream ffmpeg_stream.log 21