webrtc学习--websocket服务器(二) (web端播放h264)
文章目录
- websocket服务器
- 前言
- 本章节目标
- 准备
- 实现思路
- 服务端流程图
- 代码实现
- 服务端
- 服务端代码
- web端
- web端代码
- JMuxer
- 测试效果
- 服务端环境
- web端测试
- 资源下载
- 存在的问题
websocket服务器
前言
推荐一个零声学院免费教程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
本章节目标
实现一个websocket 传输码流服务器
可以正常的传输h264裸流
准备
接着上一章,这里将在websocket服务器的基础上,实现传输h264裸流。这样,前端接收裸流,可以正常的进行播放。
实现思路
整体是采集到的数据经过编码,然后再通过websocket传输到前端。前端接收到数据后,就可以通过JMuxer库封装成fMP4,喂给video标签,既可以实现web端播放视频。
服务端流程图
- 流程图如下
代码实现
下面分别讲解服务端和客户端的问题
服务端
服务端主要有两个,一个rtsp服务,一个websocket服务。
服务端代码
下面来展示websocket服务器代码:
服务器关键代码:
- Collection.h
#ifndef _COLLECTION_CFG_H_
#define _COLLECTION_CFG_H_#include <stdint.h>
#include <string>
#include "CollectionCfg.h"interface ICollection;
typedef std::shared_ptr<ICollection> spICollection;typedef std::function<void(uint8_t* data, int len)> NotifyVideo;interface COLLECTION_API ICollection
{virtual void start(const std::string& url) = 0;virtual void stop() = 0;
};interface COLLECTION_API CollectionFactory
{static spICollection createCollection(const NotifyVideo& video);
};#endif // _COLLECTION_CFG_H_
- CollectionData.cpp
#include "CollectionData.h"CollectionData::CollectionData(const NotifyVideo& video): m_video(video), m_i32Len(1024000), m_bQuit(false), m_nVideoIndex(-1), m_iFmtCtx(nullptr)
{m_spBuffer.reset(new uint8_t[m_i32Len], std::default_delete<uint8_t[]>());av_register_all();avcodec_register_all();av_register_all();avformat_network_init();
}CollectionData::~CollectionData()
{release();
}void CollectionData::start(const std::string& url)
{int ret = 0;AVDictionary* opts = nullptr;av_dict_set(&opts, "buffer_size", "1024000", 0);av_dict_set(&opts, "max_delay", "50000", 0);av_dict_set(&opts, "stimeout", "20000000", 0);av_dict_set(&opts, "rtsp_transport", "tcp", 0);av_dict_set(&opts, "tune", "zerolatency", 0);av_dict_set(&opts, "preset", "superfast", 0);setQuit(false);if (url == ""){return;}do{if (ret = avformat_open_input(&m_iFmtCtx, url.c_str(), 0, &opts) < 0){fprintf(stderr, "Could not open input stream file '%s'", url.c_str());break;}ret = avformat_find_stream_info(m_iFmtCtx, nullptr);if (ret < 0){fprintf(stderr, "avformat_find_stream_info fail");break;}m_nVideoIndex = av_find_best_stream(m_iFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);if (m_nVideoIndex < 0){fprintf(stderr, "no video stream fail");break;}av_dump_format(m_iFmtCtx, 0, url.c_str(), 0);m_spThread.reset(new std::thread(std::bind(&CollectionData::doThread, this)));return;} while(0);release();
}void CollectionData::doThread()
{int ret = 0;AVPacket pkt;av_init_packet(&pkt);while (!m_bQuit){ret = av_read_frame(m_iFmtCtx, &pkt);if (pkt.stream_index != m_nVideoIndex){continue;}if (m_video){m_video(pkt.data, pkt.size);}av_packet_unref(&pkt);std::this_thread::sleep_for(std::chrono::milliseconds(10));}
}void CollectionData::stop()
{setQuit(true);
}bool CollectionData::getQuit()
{return m_bQuit;
}void CollectionData::setQuit(bool bQuit)
{m_bQuit = bQuit;
}void CollectionData::thdReset()
{if (m_spThread){if (m_spThread->joinable()){m_spThread->join();}}m_spThread.reset();
}void CollectionData::release()
{setQuit(true);thdReset();if (m_iFmtCtx != nullptr){avformat_close_input(&m_iFmtCtx);}}
web端
web端代码
- web端代码实现比较简单,只需要下面的几个:
创建video标签,用来显示视频。
创建websocket,用来收取h264流。
创建JMutex用来播放h264
- index.html
<!DOCTYPE html>
<html><head><meta charset="utf-8"> 测试web播放</head><body><div><label>服务器 IP</label><input class="te" type="text" value = "127.0.0.1" id="txtip"></div><div><label>服务器端口</label><input class="te" type="text" value = "8000" id="txtport"></div><div><button id="play" type="button" onclick="play()">播放</button><button id="stop" type="button" onclick="stop()">停止</button></div><div><video id = "player" width="640" height="480" defaultPlaybackRate autoplay></video></div><script src="jmuxer.min.js"></script><script src="adapter-latest.js"></script><script type = "text/javascript">var player = nullvar websocket = null;function play() {if (player == null) {player = new JMuxer({node: 'player',mode: 'video',flushingTime: 200,fps: 30,debug: false})}if (websocket == null) {var ip = document.getElementById("txtip").value;var port = document.getElementById("txtport").value;var socketURL = "ws://" + ip + ":" + port;console.log("ws url: " + socketURL)websocket = new WebSocket(socketURL);websocket.binaryType = 'arraybuffer';websocket.addEventListener('message',function(event) {player.feed({video: new Uint8Array(event.data)})websocket.addEventListener('error', function(e) {console.log('Socket Error');});});}}function stop() { if (websocket != null) {websocket.close()websocket = null}if (player != null) {var video = document.querySelector("#player");video.srcObject = nullplayer.destroy()delete playerplayer = null}}</script></body>
</html>
- 代码讲解
# 分别是ip和端口输入框
<input class="te" type="text" value = "127.0.0.1" id="txtip">
<input class="te" type="text" value = "8000" id="txtport">
# 显示视频的标签页<video id = "player" width="640" height="480" defaultPlaybackRate autoplay></video>
# 开始播放,创建websocket和监听,并创建JMuxerfunction play() {if (player == null) {player = new JMuxer({node: 'player',mode: 'video',flushingTime: 200,fps: 30,debug: false})}if (websocket == null) {var ip = document.getElementById("txtip").value;var port = document.getElementById("txtport").value;var socketURL = "ws://" + ip + ":" + port;console.log("ws url: " + socketURL)websocket = new WebSocket(socketURL);websocket.binaryType = 'arraybuffer';websocket.addEventListener('message',function(event) {player.feed({video: new Uint8Array(event.data)})websocket.addEventListener('error', function(e) {console.log('Socket Error');});});}
# 停止播放,创建websocket和监听,并创建JMuxerfunction stop() { if (websocket != null) {websocket.close()websocket = null}if (player != null) {var video = document.querySelector("#player");video.srcObject = nullplayer.destroy()delete playerplayer = null}}
- web端界面展示
JMuxer
jmuxer可以播放h264裸流,同时可以播放音频,这个demo只是测试视频,不做音频处理
- jmuxer 代码地址:
https://github.com/samirkumardas/jmuxer.git
测试效果
下面开始展示测试效果
服务端环境
下图中,testRtspServer 是一个rtsp服务器。基于Qt和ffmpeg的抓屏rtsp服务(二)详细信息请查看这篇文章。WebSocketServed.exe 是拉取rtsp流,并利用ffmpeg获取h264裸流。通过websocket传输给前端。
web端测试
资源下载
代码下载
存在的问题
- 客户端多次开关会导致服务器崩溃,需要后续解决
- 该demo只支持h264播放,未加入音频,这个后续会加入
- 该demo只处理h264播放,未加入h265播放。h265 1080p 25fps 流畅播放暂时不公开
- 该程序只是demo,暂未处理其他影响稳定性问题
webrtc学习--websocket服务器(二) (web端播放h264)相关推荐
- netty 游戏服务器框图_基于Netty和WebSocket协议实现Web端自动打印订单服务方法与流程...
本发明涉及电子商务技术领域,尤其涉及一种基于netty和websocket协议实现web端自动打印订单服务方法. 背景技术: 电子商务是以信息网络技术为手段,以商品交换为中心的商务活动:也可理解为在互 ...
- ssm项目实现上传视频,在web端播放视频
实现的思路: 1,上传视频,将视频存放在服务器端,数据库中存放相对服务器的相对地址 2,网页端播放视频:使用ckplayer插件:www.ckplayer.com/ 参考:https://blog.c ...
- H265格式兼容各个浏览器web端播放方案
可能有很多朋友会遇到H265格式的视频流无法播放,毕竟现在很多相机都支持h265了,确实有很多优点,但是它最大的问题就是很多浏览器无法播放,也有部分浏览器能够兼容h265,但是总不能让用户指定浏览器使 ...
- Servlet学习DAY_01:服务器概念/Web服务器的作用/ Servlet概念/ 如何关联和解除Tomcat/ 创建一个Web工程 /Servlet响应流程/ Get-Post /常见异常
Servlet 什么是服务器 服务器就是一台高性能电脑 电脑上安装了提供服务的软件就称为 xxx服务器 举例: 邮件服务器: 就是在电脑上安装了提供邮件收发服务的软件 ftp服务器: 就是在电脑上安装 ...
- Socket.IO介绍:支持WebSocket、用于WEB端的即时通讯的框架
一.基本介绍 WebSocket是HTML5的一种新通信协议,它实现了浏览器与服务器之间的双向通讯.而Socket.IO是一个完全由JavaScript实现.基于Node.js.支持WebSocket ...
- php在web端播放amr语音(如微信语音)
在使用微信JSSDK的上传下载语音接口时,发现一个问题: 下载的语音在iPhone上不能播放,测试了之后原因竟然是: 微信接口返回的音频内容是amr格式的,但iPhone不支持播放此类型格式. 那么转 ...
- 腾讯实时音视频SDK[二]:web端实现
文档地址 官方文档 安装引入 //安装 npm i trtc-js-sdk //要使用的页面进行引入 import TRTC from "trtc-js-sdk"; 效果图 电脑端 ...
- 常用的视频格式文件WEB端播放代码
1.avi格式 代码片断如下: <object id="video" width="400" height="200" border= ...
- Web端播放 .amr音频文件,企业微信会话存档语音文件
前言:amr格式是微信上的语音格式,比如企业微信会话存档语音文件保存时就会遇到,由于html标签都不支持amr格式的语音文件,因此采用如下开源项目: https://github.com/BenzLe ...
- Webassembly 学习3 -- 打造web端的aac 播放器
1.引言 aac 是很常见的音频格式,压缩率比mp3 还高,H5 支持从audio 标签文件读取aac 文件并播放,但不支持从网络流中直接读取.这里借助webassembly 技术,将aac 转码成p ...
最新文章
- js立即执行函数: (function ( ){...})( ) 与 (function ( ){...}( ))
- 【Qt】DOM创建和操作XML文档
- 再见了kafka2.0时代,去掉了zk的kafka3.0才是时代新王!
- 导入依赖和加上注释后,lombok gettersetter识别不到
- linux文件IO——目录操作和文件属性
- mysql三表where查询_mysql三表查询sql语句
- 转载-C#委托之多播委托( 二)
- 进程与线程的区别?--多线程与线程池
- web安全这个行业的前景怎么样?
- Android学习小Demo(9)一个To Do List的实现
- vue-cli中理不清的assetsSubDirectory 和 assetsPublicPath
- 人月神话阅读笔记06
- 「洛谷5017」「NOIP2018」摆渡车【DP,经典好题】
- 聊聊spring security oauth2的password方式的认证
- 阿里云ACE认证学习知识点梳理
- gif录制软件 LICEcap
- 计算机考研数据库题库
- android 按钮边距,安卓button代码初始化默认内边距问题
- H5小游戏《看你有多色》扩展(辅助、眼力)
- 自学python需要安装什么-学习python要安装什么软件
热门文章
- Java中this的作用(简单说明)
- java中this和this()区别
- iterm2上传文件到linux,在iTerm2中使用Zmodem实现快速传输文件
- SecureCRT无法使用Zmodem上传下载文件
- 【计算机网络自顶向下方法】(哈工大)学习笔记
- RDPWrap远程桌面的一次脱坑
- Android 动画
- 【Axure报错】-Unable to connect to Axure Share. Please make sure you have an internet connection and try
- 制造业ERP系统具体操作流程是什么?
- 使用Mybatis拦截器实现数据分表