WebRTC, short for Web Real-time Communication, is an API that enables Web browsers to conduct real-time voice or video conversations. It became open source on June 1, 2011 and was incorporated into the World Wide Web Consortium’s W3C recommendation with support from Google, Mozilla, and Opera
WebRTC can realize point-to-point video transmission, and can be effectively used to build video communication stations.
demo
Video presentation
The fundamentals of WebRTC
The key of WebRTC video communication lies in the real-time sharing of communication equipment signaling. Assuming that there are two devices A and B, the flow chart of A successful communication is shown in the figure below.
Technology stack
Server: Use Java Spring Boot to realize webSocket signaling server front-end: vue.js
Code implementation (the complete code has been uploaded to the public number [HackDev], background reply “call” can be obtained.)
Signaling Server Setup
As mentioned above, real-time sharing of signaling is the key to realize call, so I used Java Spring Boot to build a signaling server based on WebSocket. Of course, you can also use the lighter and more convenient Node.js to build, which will be much more convenient.
@Configuration
@EnableWebSocketMessageBroker
/ / by EnableWebSocketMessageBroker use STOMP protocol to transmit messages based on agent (message broker), the browser support using the @ MessageMapping like support @ RequestMapping.
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) { //endPoint registers the protocol node and maps the specified URl
// Register an endpoint named "endpointChat" and specify the SockJS protocol. Point to point. - Yeah
registry.addEndpoint("/endpointChat").setAllowedOrigins("*").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {// Configure message Broker
// Add a point-to-point /queue message broker
registry.enableSimpleBroker("/queue"."/topic"); }}Copy the code
// Private chat controller
@RestController
public class WebSocketController {
@Autowired
private SimpMessagingTemplate messagingTemplate;
@Autowired
UserService userService;
@MessageMapping("/api/chat")
// In SpringMVC you can get the Principal directly, and the Principal contains information about the current user
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) {
// Print exceptione.printStackTrace(); }}@MessageMapping(value = "/api/entrance")
@SendTo(value = "/topic/users/list")// When the server has a message, it sends it to the browser that subscribed to the path in @sendto
public User[] say(){
System.out.println("+ + + + + + + + + + + + +");
User[] users = userService.getAllUser();
System.out.println(users[0].getUsername());
System.out.println("+ + + + + + + + + + + + +");
returnusers; }}Copy the code
Front-end WEBRTC implementation
The front end defines events such as signaling creation and sharing. Here I choose the VUE framework to build.
- Connect to the signaling server
this.sock = new SockJS("/root/endpointChat")
this.stomp = Stomp.over(this.sock)
Copy the code
- dial
let _self = this
_self.targetUsername = targetUsername
_self.stomp.send("/api/chat", {}, JSON.stringify({'username': targetUsername,
'type': 'tryCall'.'content': JSON.stringify(_self.option)
}))
Copy the code
- B agrees to answer
_self.stomp.send("/api/chat", {}, JSON.stringify({'username': _self.targetUsername,
'type': 'accept'.'content': ' '
}))
// Get the media stream
const videoTracks = _self.localStream.getVideoTracks();
const audioTracks = _self.localStream.getAudioTracks();
// Define a local connection
_self.localPeerConnection = new RTCPeerConnection({});
// Define a remote connection
_self.remotePeerConnection = new RTCPeerConnection({});
Copy the code
- A learns that B agrees to answer
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)}))
},
Copy the code
The complete code has been uploaded to the public account [z students who can program], and you can get it by replying to “call” in the background.