私密的一对一视频直播聊天体验
直播间一对一展示代码
webrtc+websocket 直接上代码
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
@Component
@ServerEndpoint("/groupChat/{roomId}/{username}")
public class GroupChatController {
// 保存 聊天室id -> 聊天室成员 的映射关系
private static ConcurrentHashMap<String, List<Session>> rooms = new ConcurrentHashMap<>();
// 收到消息调用的方法,群成员发送消息
@OnMessage
public void onMessage(@PathParam("roomId") String roomId,
@PathParam("username") String username, String message) {
List<Session> sessionList = rooms.get(roomId);
System.out.println("sessionList"+sessionList);
// 分别向聊天室的成员发送消息
for (Session session : sessionList) {
try {
String text=username+": "+message;
session.getBasicRemote().sendText(text);
} catch (IOException e) {
e.printStackTrace();
}
}
// lambda表达式写法
// sessionList.forEach(item -> {
// try {
// String text = username + ": " + message;
// item.getBasicRemote().sendText(text);
// } catch (IOException e) {
// e.printStackTrace();
// }
// });
}
// 建立连接调用的方法,群成员加入
@OnOpen
public void onOpen(Session session, @PathParam("roomId") String roomId, @PathParam("name") String name) {
List<Session> sessionList = rooms.get(roomId);
if (sessionList == null) {
sessionList = new ArrayList<>();
rooms.put(roomId, sessionList);
}
sessionList.add(session);
System.out.println("成员加入---- 聊天室号:" + roomId + " 当前聊天室人数:" + sessionList.size());
}
// 关闭连接调用的方法,群成员退出
@OnClose
public void onClose(Session session, @PathParam("roomId") String roomId) {
List<Session> sessionList = rooms.get(roomId);
sessionList.remove(session);
System.out.println("成员退出---- 聊天室号:" + roomId + " 当前聊天室人数:" + sessionList.size());
}
// 传输消息错误调用的方法
@OnError
public void OnError(Throwable error) {
System.out.println("消息传递出错");
}
}
<style>
.container {
margin-top: 30px;
margin-left: 30px;
}
.span1 {
display: inline-block;
width: 80px;
font-size: 13px;
}
input {
width: 200px;
height: 30px;
outline: none;
border: 1px solid #3998f7;
border-radius: 3px;
padding: 0 10px;
}
input:hover,
textarea:hover {
box-shadow: 0 0 3px #3998f7;
}
#name {
margin-top: 15px;
}
button {
width: 100px;
height: 30px;
outline: none;
color: #fff;
font-size: 13px;
font-weight: bold;
background-color: #168ed1;
border: none;
border-radius: 5px;
cursor: pointer;
}
#connectBtn,
#content,
#sendBtn,
#closeBtn {
margin-top: 10px;
}
#messages {
margin-top: 20px;
}
textarea {
width: 300px;
height: 80px;
outline: none;
border: 1px solid #3998f7;
border-radius: 3px;
color: rgba(0, 0, 0, 0.7);
font-size: 13px;
font-weight: bold;
padding: 5px;
}
#messages, .me, .name {
color: rgba(0, 0, 0, 0.7);
font-size: 14px;
font-weight: bold;
}
.me {
color: red;
}
.name {
color: royalblue;
}
</style>
昵称:
刷新
连接
发送 退出
网上看着扒下来的一个 聊天室 前端后端
视频直播加聊天室
昵称:
刷新
连接
发送 退出
js代码
// 产生随机数
if (!location.hash) {
location.hash = Math.floor(Math.random() * 0xFFFFFF).toString(16);
}
// 获取房间号
var roomHash = location.hash.substring(1);
// 放置你自己的频道id, 这是我注册了 ScaleDrone 官网后,创建的channel
// 你也可以自己创建
var drone = new ScaleDrone(‘87fYv4ncOoa0Cjne’);
// 房间名必须以 'observable-'开头
var roomName = ‘observable-’ + roomHash;
var configuration = {
iceServers: [{
urls: ‘stun:stun.l.google.com:19302’ // 使用谷歌的stun服务
}]
};
var room;
var pc;
function onSuccess() {}
function onError(error) {
console.error(error);
}
drone.on(‘open’, function(error){
if (error) { return console.error(error);}
room = drone.subscribe(roomName);
room.on('open', function(error){
if (error) {onError(error);}
});
// 已经链接到房间后,就会收到一个 members 数组,代表房间里的成员
// 这时候信令服务已经就绪
room.on('members', function(members){
console.log('MEMBERS', members);
// 如果你是第二个链接到房间的人,就会创建offer
var isOfferer = members.length === 2;
startWebRTC(isOfferer);
});
});
// 通过Scaledrone发送信令消息
function sendMessage(message) {
drone.publish({
room: roomName,
message
});
}
function startWebRTC(isOfferer) {
pc = new RTCPeerConnection(configuration);
// 当本地ICE Agent需要通过信号服务器发送信息到其他端时
// 会触发icecandidate事件回调
pc.onicecandidate = function(event){
if (event.candidate) {
sendMessage({ 'candidate': event.candidate });
}
};
// 如果用户是第二个进入的人,就在negotiationneeded 事件后创建sdp
if (isOfferer) {
// onnegotiationneeded 在要求sesssion协商时发生
pc.onnegotiationneeded = function() {
// 创建本地sdp描述 SDP (Session Description Protocol) session描述协议
pc.createOffer().then(localDescCreated).catch(onError);
};
}
// 当远程数据流到达时,将数据流装载到video中
pc.onaddstream = function(event){
remoteVideo.srcObject = event.stream;
};
// 获取本地媒体流
navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
}).then( function(stream) {
// 将本地捕获的视频流装载到本地video中
localVideo.srcObject = stream;
// 将本地流加入RTCPeerConnection 实例中 发送到其他端
pc.addStream(stream);
}, onError);
// 从Scaledrone监听信令数据
room.on('data', function(message, client){
// 消息是我自己发送的,则不处理
if (client.id === drone.clientId) {
return;
}
if (message.sdp) {
// 设置远程sdp, 在offer 或者 answer后
pc.setRemoteDescription(new RTCSessionDescription(message.sdp), function(){
// 当收到offer 后就接听
if (pc.remoteDescription.type === 'offer') {
pc.createAnswer().then(localDescCreated).catch(onError);
}
}, onError);
}
else if (message.candidate) {
// 增加新的 ICE canidatet 到本地的链接中
pc.addIceCandidate(
new RTCIceCandidate(message.candidate), onSuccess, onError
);
}
});
}
function localDescCreated(desc) {
pc.setLocalDescription(desc, function(){
sendMessage({ ‘sdp’: pc.localDescription });
},onError);
}
这些都是网上扒下来整理啦一下 侵权什么的联系我秒删