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. Eclipse 创建OSGI项目并调试

    File->new->Plug-in Project

  2. Centos7中防火墙打开3306端口(亲测)

    开放3306端口 firewall-cmd --zone=public --add-port=3306/tcp --permanent     开启防火墙 systemctl start firewa ...

  3. Java新特性中的Preview功能如何运行和调试

    在每个Java新版本发布的特性中,都会包含一些Preview(预览)功能,这些功能主要用来给开发者体验并收集建议.所以,Preview阶段的功能并不是默认开启的. 如果想体验某个Java版本中的Pre ...

  4. c语言代码练习15

    //使用togo跳转代码,阻止关机#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <string.h> ...

  5. 算法1:寻找完数(JS)

    任务一:寻找完数 打印10000以内的完数 完数:与自己所有因子之和相等的数. 1 let sum = 0, i, j; // 定义变量sum.i和j 2 3 for (i = 1; i < 1 ...

  6. RK3588平台产测之ArmSoM产品低温环境测试

    1. 简介 专栏总目录 ArmSoM团队在产品量产之前都会对产品做几次专业化的功能测试以及性能压力测试,以此来保证产品的质量以及稳定性 优秀的产品都要进行严苛的多次全方位的功能测试以及性能压力测试才能 ...

  7. CF1676G

    题目简化和分析: 求一颗子树的黑白两数是否相等. 我们设黑 \(1\),白 \(-1\),若某一棵子树的权值为 \(0\),说明此刻的黑白个数相等,贡献加一. 从根搜索,每次将值传递给父亲,判断父亲此 ...

  8. 深度解读MediaBox SDKs如何实现技术架构升级

    本专栏将分享阿里云视频云MediaBox系列技术文章,深度剖析音视频开发利器的技术架构.技术性能.开发能效和最佳实践,一起开启音视频的开发之旅.本文为MediaBox技术架构篇,重点从音视频终端SDK ...

  9. 让物体动起来,Unity的几种移动方式

    一.前言 在大部分的Unity游戏开发中,移动是极其重要的一部分,移动的手感决定着游戏的成败,一个优秀的移动手感无疑可以给游戏带来非常舒服的体验.而Unity中有多种移动方法,使用Transform, ...

  10. QT(1)- QString

    QT(1)- QString 1 简介 在Qt中表示字符串的类是QString类,它存储字符串是采用的Unicode码,编码方式是使用UTF-16来进行编码的,也就是一个字符(两个字节),一个中文汉字 ...