websocket实现实时直播

这篇文章我首发于简书,拿到这里发表不过分吧?点个赞再走呗!
作为一名web开发者,我使用websocket实现实时直播(滑鸡版)。
为什么是滑鸡版呢?因为他上不了生产,只能了解一下直播的思路,不过也挺有意思的!

思路

开发思路,我们使用websocket实现数据传输,后台就用spring boot集成了websocket,当然用netty自定义更好,我这里直接拿spring全家桶快速开发。
主播视频数据实时推送到服务端,然后由websocket推送给用户观看。最后把弹幕给实现了,这里我用Chrome浏览器+笔记本,谷歌+360极速浏览器。有些浏览器调用摄像头函数可能不一致,导致无法启动。
项目源码:https://github.com/xcocean/wszb

一、创建项目

创建一个spring boot项目wszb快速开发,maven如下:

    <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

二、实现websocket服务端—画面传输

配置

@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

controller

用来做页面控制

@Controller
public class WsController {
/**
* 用户可以看到画面
*/
@GetMapping("")
public String index() {
return "index";
} /**
* 主播直播的画面
*/
@GetMapping("video")
public String video() {
return "video";
}
}

视频websocket

package com.lingkang.wszb.websocket;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component; @ServerEndpoint(value = "/v")
@Component
public class VideoWebsocket { //concurrent包的线程安全,用来存放每个客户端对应的WebSocket
private static ConcurrentHashMap<String, VideoWebsocket> webSocket = new ConcurrentHashMap<String, VideoWebsocket>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
// 表示主播
private static final String video = "v";
// 给用户一个id
private static int id = 0; private static String thisUser = ""; /**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
try {
String type = session.getQueryString();
if (type.equals("video")) {
// 表示主播
thisUser = video;
webSocket.put(thisUser, this);
System.out.println("有人加入,是主播");
} else {
// 表示用户
thisUser = String.valueOf(id);
webSocket.put(thisUser, this);
System.out.println("有人加入,是用户");
id = id + 1;
}
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) throws Exception {
System.out.println("关闭连接:" + thisUser);
//需要清除当前和移除内存里的,不然还能接收信息
session.close();
webSocket.remove(thisUser);
} /**
* 收到客户端消息后调用的方法
*/
//@OnMessage(maxMessageSize = 12)表示超出12个字节会自动关闭这个连接
@OnMessage(maxMessageSize = 56666)
public void onMessage(String message, Session session) throws IOException {
System.out.println("来自客户端的消息:" + message);
//群发消息
Iterator iter = webSocket.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
if (!entry.getKey().equals(video)) {//主播除外
webSocket.get(entry.getKey()).session.getBasicRemote().sendText(message);
}
}
} /**
* 发生错误时调用
*/
@OnError
public void onError(Session session, Throwable error) throws Exception {
System.out.println("发生错误:" + thisUser);
session.close();
webSocket.remove(thisUser);
}
}

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户观看页面</title>
</head>
<body>
<h2 style="text-align: center;">这是用户观看页面</h2> <img id="receiver" style="width: 500px;height: 450px;">
<script type="text/javascript" charset="utf-8">
//创建一个socket实例 ?user用来代表用户
var socket = new WebSocket("ws://localhost:8080/v?user");
//打开socket
socket.onopen = function () {
console.log("open success")
}
var image = document.getElementById('receiver');
//接收到消息的回调方法
socket.onmessage = function (data) {
image.src = data.data;
}
//连接关闭的回调方法
socket.onclose = function () {
console.log("close");
}
</script>
</body>
</html>

video.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>video</title>
</head>
<body>
<h2 style="text-align: center;">这是主播页面</h2>
<input type="button" title="开启摄像头" value="开启摄像头" onclick="getMedia()"/>
<video id="video" width="500px" height="500px" autoplay="autoplay"></video>
<canvas id="canvas" width="500px" height="500px"></canvas>
<button onclick="start()">开始直播</button>
<button onclick="stop()">停止直播</button>
<script>
//获得video摄像头区域
var video = document.getElementById("video");
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d'); function getMedia() {
var constraints = {
video: {width: 500, height: 500},
audio: false
};
/*
这里介绍新的方法:H5新媒体接口 navigator.mediaDevices.getUserMedia()
这个方法会提示用户是否允许媒体输入,(媒体输入主要包括相机,视频采集设备,屏幕共享服务,麦克风,A/D转换器等)
返回的是一个Promise对象。
如果用户同意使用权限,则会将 MediaStream对象作为resolve()的参数传给then()
如果用户拒绝使用权限,或者请求的媒体资源不可用,则会将 PermissionDeniedError作为reject()的参数传给catch()
*/
var promise = navigator.mediaDevices.getUserMedia(constraints);
promise.then(function (MediaStream) {
video.srcObject = MediaStream;
video.play();
}).catch(function (PermissionDeniedError) {
console.log(PermissionDeniedError);
})
} var socket = new WebSocket("ws://localhost:8080/v?video");
//打开socket socket.onopen = function () {
console.log("open success")
} //接收到消息的回调方法
socket.onmessage = function (event) {
console.log(event)
} //连接关闭的回调方法
socket.onclose = function () {
console.log("close");
} var interval function start() {
interval = window.setInterval(function () {
ctx.drawImage(video, 0, 0, 500, 500);
socket.send(canvas.toDataURL("image/jpeg", 0.5));
}, 60);
} function stop() {
clearInterval(interval)
}
</script>
</body>
</html>

演示:专业操作,请勿模仿

实现即时弹幕

弹幕我就懒得实现了,再new 一个websocket做弹幕链接,然后用js把接收的弹幕在显示地方移动过来就行了。

http实时语音

https://www.jianshu.com/p/7965c9faafa6

websocket实现实时直播的更多相关文章

  1. WebSocket+MSE——HTML5 直播技术解析

    作者 | 刘博(又拍云多媒体开发工程师) 当前为了满足比较火热的移动 Web 端直播需求,一系列的 HTML5 直播技术迅速的发展起来. 常见的可用于 HTML5 的直播技术有 HLS.WebSock ...

  2. Asp.net+WebSocket+Emgucv实时人脸识别

    上个月在网上看到一个用web实现简单AR效果的文章,然后自己一路折腾,最后折腾出来一个 Asp.net+WebSocket+Emgucv实时人脸识别的东西,网上也有不少相关资料,有用winform的也 ...

  3. [转]使用 HTML5 WebSocket 构建实时 Web 应用

    HTML5 WebSocket 简介和实战演练 本文主要介绍了 HTML5 WebSocket 的原理以及它给实时 Web 开发带来的革命性的创新,并通过一个 WebSocket 服务器和客户端的案例 ...

  4. 使用 HTML5 WebSocket 构建实时 Web 应用

    原文地址:http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/ HTML5 WebSocket 简介和实战演练 本文主要介绍 ...

  5. springboot搭建一个简单的websocket的实时推送应用

    说一下实用springboot搭建一个简单的websocket 的实时推送应用 websocket是什么 WebSocket是一种在单个TCP连接上进行全双工通信的协议 我们以前用的http协议只能单 ...

  6. (转)使用 HTML5 WebSocket 构建实时 Web 应用

    HTML5 WebSocket 简介和实战演练 本文主要介绍了 HTML5 WebSocket 的原理以及它给实时 Web 开发带来的革命性的创新,并通过一个 WebSocket 服务器和客户端的案例 ...

  7. WebSocket实现实时聊天系统

    WebSocket实现实时聊天系统 等闲变却故人心,却道故人心易变. 简介:前几天看了WebSocket,今天体验下它的实时聊天. 一.项目介绍 WebSocket 实时聊天系统自己一个一码的搞出来还 ...

  8. 使用WebSocket构建实时WEB

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/SJQ. http://www.cnblogs.com/shijiaqi1066/p/3795075.html ...

  9. Practical Node.js (2018版) 第9章: 使用WebSocket建立实时程序,原生的WebSocket使用介绍,Socket.IO的基本使用介绍。

    Real-Time Apps with WebSocket, Socket.IO, and DerbyJS 实时程序的使用变得越来越广泛,如传统的交易,游戏,社交,开发工具DevOps tools, ...

  10. Django实现websocket完成实时通讯,聊天室,在线客服等

    一 什么是Websocket WebSocket是一种在单个TCP连接上进行全双工通信的协议 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在WebS ...

随机推荐

  1. Linux平台Oracle 23c单实例 安装部署配置 快速参考

    转眼间已经2023年,再有一周就要过年了,在这里先给大家拜个早年,祝大家新的一年万事顺利. Oracle如今版本号也和年份挂钩,在前段时间的OCW上也宣布发布了beta版本的23c,因为23c是继19 ...

  2. DICOM PS3.7 2021a - Message Exchange

    PS3.7 DICOM PS3.7 2021a - Message Exchange DICOM Standards Committee Copyright 2021 NEMA A DICOM pub ...

  3. 报Bug的礼仪

    不要对1个程序员说:你的代码有Bug.他的第1反应是:1.你的环境有问题吧:2.傻逼你会用吗? 如果你委婉的说:你这个程序和预期的有点不1致,你看看是不是我的打开姿势有问题?他本能的会想:擦,是不是出 ...

  4. 【纯干货】IOS手机使用Charles抓包

    一.Charles 下载地址 https://www.charlesproxy.com/ 二.Charles 激活 1.生成激活码 生成激活码:https://www.zzzmode.com/myto ...

  5. 初探富文本之React实时预览

    初探富文本之React实时预览 在前文中我们探讨了很多关于富文本引擎和协同的能力,在本文中我们更偏向具体的应用组件实现.在一些场景中比如组件库的文档编写时,我们希望能够有实时预览的能力,也就是用户可以 ...

  6. 关于 Python 字符串切片的小领悟

    1. 什么是 Python 字符串切片? 例如存在字符串 str2 = "abcd1234" ,有以下简单的切片应用. str2[0] # a str2[0:3] # abc st ...

  7. 【SqlServer】存储过程:批量查询数据库下表的元数据

    一.查询单张表 1.1 根据表名查询表结构 --快速查看表结构(比较全面的) DECLARE @tableName NVARCHAR(MAX); SET @tableName = N'YMUS'; - ...

  8. c#中建造者设计模式详解

    基础介绍:   将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.   说白了就是将一个复杂的对象拆分成一个一个零件,然后按照既定顺序和规则进行组装,最终形成这个相对复杂的对象 ...

  9. 题解 CF690C2

    题目大意: 给你一棵树,求一下直径 题目分析: emm,怎么说吧,就是树的直径的裸板子. 可能有人不大理解,明明是图,你为什么要说是给定一棵树. 大家可以自行验证一下,满足如下两个性质的是否是一棵树: ...

  10. P5318 查阅文献

    题意大概意思就是分别用dfs与bfs遍历一个图,特殊要求是从编号小的点开始遍历. 用邻接表存图,至今我也没想明白怎么才可以从编号小的点开始遍历,明白是排序,但是不知道如何排序,题解中的排序方法是:按照 ...