Browse Source

feat: add audio call

one-file
konenet 4 years ago
parent
commit
4785290b46
  1. 118
      src/chat/Panel.jsx
  2. 5
      src/chat/common/constant/Constant.jsx

118
src/chat/Panel.jsx

@ -28,6 +28,7 @@ import InfiniteScroll from 'react-infinite-scroll-component';
import moment from 'moment'; import moment from 'moment';
import { axiosGet, axiosPostBody } from './util/Request'; import { axiosGet, axiosPostBody } from './util/Request';
import * as Params from './common/param/Params' import * as Params from './common/param/Params'
import * as Constant from './common/constant/Constant'
import UserInfo from './component/UserInfo' import UserInfo from './component/UserInfo'
import protobuf from './proto/proto' import protobuf from './proto/proto'
@ -115,6 +116,7 @@ class Panel extends React.Component {
super(props) super(props)
this.state = { this.state = {
isRecord: false, isRecord: false,
onlineType: 1, // 线 12
user: {}, user: {},
comments: [], comments: [],
submitting: false, submitting: false,
@ -305,7 +307,7 @@ class Panel extends React.Component {
} }
// webrtc // webrtc
if (messagePB.type === "webrtc") { if (messagePB.type === Constant.MESSAGE_TRANS_TYPE) {
this.dealWebRtcMessage(messagePB); this.dealWebRtcMessage(messagePB);
return; return;
} }
@ -368,7 +370,7 @@ class Panel extends React.Component {
to: this.state.toUser, to: this.state.toUser,
messageType: this.state.messageType, messageType: this.state.messageType,
content: JSON.stringify(candidate), content: JSON.stringify(candidate),
type: "webrtc", type: Constant.MESSAGE_TRANS_TYPE,
} }
let message = protobuf.lookup("protocol.Message") let message = protobuf.lookup("protocol.Message")
const messagePB = message.create(data) const messagePB = message.create(data)
@ -383,8 +385,13 @@ class Panel extends React.Component {
*/ */
peer.ontrack = (e) => { peer.ontrack = (e) => {
if (e && e.streams) { if (e && e.streams) {
let remoteVideo = document.getElementById("remoteVideo"); if (this.state.onlineType === 1) {
remoteVideo.srcObject = e.streams[0]; let remoteVideo = document.getElementById("remoteVideo");
remoteVideo.srcObject = e.streams[0];
} else {
let remoteAudio = document.getElementById("audioPhone");
remoteAudio.srcObject = e.streams[0];
}
} }
}; };
} }
@ -407,11 +414,26 @@ class Panel extends React.Component {
if (!this.checkMediaPermisssion()) { if (!this.checkMediaPermisssion()) {
return; return;
} }
let preview = document.getElementById("preview1"); let preview
let video = false;
if (messagePB.contentType === Constant.VIDEO_ONLINE) {
preview = document.getElementById("preview1");
video = true
this.setState({
onlineType: 1,
})
} else {
preview = document.getElementById("audioPhone");
this.setState({
onlineType: 2,
})
}
navigator.mediaDevices navigator.mediaDevices
.getUserMedia({ .getUserMedia({
audio: true, audio: true,
video: true, video: video,
}).then((stream) => { }).then((stream) => {
preview.srcObject = stream; preview.srcObject = stream;
stream.getTracks().forEach(track => { stream.getTracks().forEach(track => {
@ -428,13 +450,13 @@ class Panel extends React.Component {
fromUsername: localStorage.username, fromUsername: localStorage.username,
from: this.state.fromUser, from: this.state.fromUser,
to: this.state.toUser, to: this.state.toUser,
messageType: this.state.messageType, messageType: messagePB.contentType,
content: JSON.stringify(answer), content: JSON.stringify(answer),
type: "webrtc", type: Constant.MESSAGE_TRANS_TYPE,
} }
let message = protobuf.lookup("protocol.Message") let message = protobuf.lookup("protocol.Message")
const messagePB = message.create(data) const messagePBNew = message.create(data)
socket.send(message.encode(messagePB).finish()) socket.send(message.encode(messagePBNew).finish())
}) })
}); });
}); });
@ -464,6 +486,10 @@ class Panel extends React.Component {
* @returns 媒体权限是否开启 * @returns 媒体权限是否开启
*/ */
checkMediaPermisssion = () => { checkMediaPermisssion = () => {
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia; //
if (!navigator || !navigator.mediaDevices) { if (!navigator || !navigator.mediaDevices) {
message.error("获取摄像头权限失败!") message.error("获取摄像头权限失败!")
return false; return false;
@ -1023,16 +1049,13 @@ class Panel extends React.Component {
* 开启视频电话 * 开启视频电话
*/ */
startVideoOnline = () => { startVideoOnline = () => {
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia; //
if (!this.checkMediaPermisssion()) { if (!this.checkMediaPermisssion()) {
return; return;
} }
let preview = document.getElementById("preview1"); let preview = document.getElementById("preview1");
this.setState({ this.setState({
onlineType: 1,
isRecord: true, isRecord: true,
rtcType: 'offer' rtcType: 'offer'
}) })
@ -1056,8 +1079,9 @@ class Panel extends React.Component {
from: this.state.fromUser, from: this.state.fromUser,
to: this.state.toUser, to: this.state.toUser,
messageType: this.state.messageType, messageType: this.state.messageType,
contentType: Constant.VIDEO_ONLINE,
content: JSON.stringify(offer), content: JSON.stringify(offer),
type: "webrtc", type: Constant.MESSAGE_TRANS_TYPE,
} }
let message = protobuf.lookup("protocol.Message") let message = protobuf.lookup("protocol.Message")
const messagePB = message.create(data) const messagePB = message.create(data)
@ -1081,10 +1105,20 @@ class Panel extends React.Component {
this.recorder.stop() this.recorder.stop()
this.recorder = null this.recorder = null
} }
let preview = document.getElementById("preview1"); let preview1 = document.getElementById("preview1");
if (preview1 && preview1.srcObject && preview1.srcObject.getTracks()) {
preview1.srcObject.getTracks().forEach((track) => track.stop());
}
let preview = document.getElementById("preview");
if (preview && preview.srcObject && preview.srcObject.getTracks()) { if (preview && preview.srcObject && preview.srcObject.getTracks()) {
preview.srcObject.getTracks().forEach((track) => track.stop()); preview.srcObject.getTracks().forEach((track) => track.stop());
} }
let audioPhone = document.getElementById("audioPhone");
if (audioPhone && audioPhone.srcObject && audioPhone.srcObject.getTracks()) {
audioPhone.srcObject.getTracks().forEach((track) => track.stop());
}
this.dataChunks = [] this.dataChunks = []
if (this.interval) { if (this.interval) {
@ -1101,6 +1135,52 @@ class Panel extends React.Component {
}) })
} }
/**
* 开启语音电话
*/
startAudioOnline = () => {
if (!this.checkMediaPermisssion()) {
return;
}
this.setState({
onlineType: 2,
isRecord: true,
rtcType: 'offer'
})
navigator.mediaDevices
.getUserMedia({
audio: true,
video: false,
}).then((stream) => {
stream.getTracks().forEach(track => {
peer.addTrack(track, stream);
});
// offer
peer.createOffer()
.then(offer => {
peer.setLocalDescription(offer);
let data = {
fromUsername: localStorage.username,
from: this.state.fromUser,
to: this.state.toUser,
messageType: this.state.messageType, // 1. 2.
contentType: Constant.AUDIO_ONLINE, //
content: JSON.stringify(offer),
type: Constant.MESSAGE_TRANS_TYPE, //
}
let message = protobuf.lookup("protocol.Message")
const messagePB = message.create(data)
socket.send(message.encode(messagePB).finish())
});
});
this.setState({
mediaPanelDrawerVisible: true
})
}
/** /**
* 屏幕共享 * 屏幕共享
@ -1282,11 +1362,10 @@ class Panel extends React.Component {
<Tooltip title="语音聊天"> <Tooltip title="语音聊天">
<Button <Button
shape="circle" shape="circle"
onClick={this.startVideoOnline} onClick={this.startAudioOnline}
style={{ marginRight: 10 }} style={{ marginRight: 10 }}
icon={<PhoneOutlined />} icon={<PhoneOutlined />}
// disabled={toUser === ''} disabled={toUser === ''}
disabled
/> />
</Tooltip> </Tooltip>
<Tooltip title="视频聊天"> <Tooltip title="视频聊天">
@ -1384,6 +1463,7 @@ class Panel extends React.Component {
<img id="receiver" width={this.state.currentScreen.width} height="auto" alt="" /> <img id="receiver" width={this.state.currentScreen.width} height="auto" alt="" />
<canvas id="canvas" width={this.state.currentScreen.width} height={this.state.currentScreen.height} /> <canvas id="canvas" width={this.state.currentScreen.width} height={this.state.currentScreen.height} />
<audio id="audioPhone" autoPlay controls />
</Drawer> </Drawer>
</> </>
); );

5
src/chat/common/constant/Constant.jsx

@ -0,0 +1,5 @@
export const AUDIO_ONLINE = 6; //
export const VIDEO_ONLINE = 7; //
export const MESSAGE_TRANS_TYPE = "webrtc"; // heatbeat,线webrtc
Loading…
Cancel
Save