🔞爲了和小姐姐私密視頻聊天,我開發了一個點對點視頻聊天室。
WebRTC,名稱源自網頁即時通信(英語:Web Real-Time Communication)的縮寫,是一個支持網頁瀏覽器進行實時語音對話或視頻對話的API。它於2011年6月1日開源並在Google、Mozilla、Opera支持下被納入萬維網聯盟的W3C推薦標準
WebRTC能夠實現點對點的視頻傳輸,能夠有效運用與視頻通訊站的搭建。
演示
webrtc開發通話站演示.mp4
WebRTC的基本原理
WebRTC視頻通訊的關鍵在於通訊設備信令的實時分享,假定有A,B兩臺設備,則一次成功的通訊流程圖如下圖所示。
技術棧
服務端:使用java spring boot實現websocket信令服務器
前端:vue.js
代碼實現 (完整代碼已上傳至公衆號【HackDev】,後臺回覆「通話」即可獲取。)
信令服務器搭建
前面提到,信令的實時分享是實現通話的重點,爲此我使用了Java spring boot搭建基於WebSocket的信令服務器。當然大家也可以使用更加輕量便捷的node.js來搭建,會方便很多。
@Configuration
@EnableWebSocketMessageBroker
//通過EnableWebSocketMessageBroker 開啓使用STOMP協議來傳輸基於代理(message broker)的消息,此時瀏覽器支持使用@MessageMapping 就像支持@RequestMapping一樣。
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) { //endPoint 註冊協議節點,並映射指定的URl
//註冊一個名字爲"endpointChat" 的endpoint,並指定 SockJS協議。 點對點-用
registry.addEndpoint("/endpointChat").setAllowedOrigins("*").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {//配置消息代理(message broker)
//點對點式增加一個/queue 消息代理
registry.enableSimpleBroker("/queue","/topic");
}
}
// 私信聊天的控制器
@RestController
public class WebSocketController {
@Autowired
private SimpMessagingTemplate messagingTemplate;
@Autowired
UserService userService;
@MessageMapping("/api/chat")
//在springmvc 中可以直接獲得principal,principal 中包含當前用戶的信息
public void handleChat(Principal principal, MessagePara messagePara) {
System.out.println(messagePara.getUsername());
System.out.println(messagePara.getContent());
String currentUserName = principal.getName();
System.out.println(currentUserName);
try {
messagePara.setFrom(principal.getName());
System.out.println("from" + messagePara.getFrom());
Integer u_id = userService.getIdByName(currentUserName);
messagingTemplate.convertAndSendToUser(messagePara.getUsername(),
"/queue/notifications",
messagePara);
} catch (Exception e) {
// 打印異常
e.printStackTrace();
}
}
@MessageMapping(value = "/api/entrance")
@SendTo(value = "/topic/users/list")//當服務端有消息時,會對訂閱了@SendTo中的路徑的瀏覽器發送消息
public User[] say(){
System.out.println("+++++++++++++");
User[] users = userService.getAllUser();
System.out.println(users[0].getUsername());
System.out.println("+++++++++++++");
return users;
}
}
前端webrtc實現
前端主要需要定義信令的創建和分享等事件。這裏我選用了vue框架來搭建。
- 連接到信令服務器
this.sock = new SockJS("/root/endpointChat")
this.stomp = Stomp.over(this.sock)
- 撥號
let _self = this
_self.targetUsername = targetUsername
_self.stomp.send("/api/chat", {}, JSON.stringify({'username': targetUsername,
'type': 'tryCall',
'content': JSON.stringify(_self.option)
}))
- B同意接聽
_self.stomp.send("/api/chat", {}, JSON.stringify({'username': _self.targetUsername,
'type': 'accept',
'content': ''
}))
// 獲取媒體流
const videoTracks = _self.localStream.getVideoTracks();
const audioTracks = _self.localStream.getAudioTracks();
// 定義本地連接
_self.localPeerConnection = new RTCPeerConnection({});
// 定義遠程連接
_self.remotePeerConnection = new RTCPeerConnection({});
- A得知B同意接聽
async call(targetUsername) {
let _self = this
trace('localPeerConnection createOffer start.');
const description = await _self.localPeerConnection.createOffer({offerToReceiveVideo: 1})
trace(`Offer from localPeerConnection:\n${description.sdp}`);
trace('localPeerConnection setLocalDescription start.');
console.log("==============")
console.log(description)
console.log("==============")
_self.localPeerConnection.setLocalDescription(description)
console.log("send websocket")
_self.stomp.send("/api/chat", {}, JSON.stringify({'username': targetUsername,
'type': 'send',
'content': JSON.stringify(description)}))
},
完整代碼已上傳至公衆號【HackDev】,後臺回覆「通話」即可獲取。