Frontend: Blobs are existing!

This commit is contained in:
ADAMJR 2021-10-04 19:08:14 +01:00
parent 106f61f881
commit 71f9c3b3ae
8 changed files with 59 additions and 15 deletions

View File

@ -27,6 +27,16 @@ export class VoiceService {
this.connections.set(channelId, channelConnections);
}
public setForUser(channelId: string, data: ChannelTypes.VoiceConnection) {
const channelConnections = this.getOrCreate(channelId);
const index = channelConnections.findIndex(c => c.userId === data.userId);
channelConnections[index] = data;
this.connections.set(channelId, channelConnections);
return this.getForUser(channelId, data.userId);
}
public remove(channelId: string, userId: string) {
const channelConnections = this.getOrCreate(channelId);
const index = channelConnections.findIndex(c => c.userId === userId);

View File

@ -8,6 +8,7 @@ import { VoiceService } from '../../voice/voice-service';
import Users from '../../data/users';
import { SelfUserDocument } from '../../data/models/user';
import ChannelLeave from './channel-leave';
import VoiceData from './voice-data';
export default class implements WSEvent<'CHANNEL_JOIN'> {
on = 'CHANNEL_JOIN' as const;
@ -17,6 +18,7 @@ export default class implements WSEvent<'CHANNEL_JOIN'> {
private voice = Deps.get<VoiceService>(VoiceService),
private users = Deps.get<Users>(Users),
private leaveEvent = Deps.get<ChannelLeave>(ChannelLeave),
private voiceDataEvent = Deps.get<VoiceData>(VoiceData),
) {}
public async invoke(ws: WebSocket, client: Socket, { channelId }: WS.Params.ChannelJoin) {
@ -35,7 +37,7 @@ export default class implements WSEvent<'CHANNEL_JOIN'> {
if (doesExist)
throw new TypeError('User already connected to voice');
this.voice.add(channelId, { stream: null, userId });
this.voice.add(channelId, { userId });
await Promise.all([
client.join(channelId),
@ -56,6 +58,9 @@ export default class implements WSEvent<'CHANNEL_JOIN'> {
userId: user.id,
voice: user.voice,
} as WS.Args.VoiceStateUpdate);
// send empty event to initialize cycle of sending data
await this.voiceDataEvent.invoke(ws, client, { channelId });
}
private async updateVoiceState(user: SelfUserDocument, channelId: string) {

View File

@ -12,16 +12,13 @@ export default class implements WSEvent<'VOICE_DATA'> {
private voiceService = Deps.get<VoiceService>(VoiceService),
) {}
public async invoke(ws: WebSocket, client: Socket, { channelId }: WS.Params.VoiceData) {
public async invoke(ws: WebSocket, client: Socket, { channelId, blob }: WS.Params.VoiceData) {
const userId = ws.sessions.get(client.id);
// receive data
// channel id of voice channel?
// -> if specified in args it can be spoofed
// -> if we constantly get user voice state from db that's very inefficient
// send audio back to client
const connections = this.voiceService.getForUser(channelId, userId);
const connections = this.voiceService.setForUser(channelId, { blob, userId });
client.emit('VOICE_DATA', { connections } as WS.Args.VoiceData);
client.emit('VOICE_DATA', { channelId, connections } as WS.Args.VoiceData);
}
}

View File

@ -49,6 +49,7 @@
"web-vitals": "^1.1.2"
},
"devDependencies": {
"@types/dom-mediacapture-record": "^1.0.10",
"@types/javascript-time-ago": "^2.0.3",
"@types/promise-timeout": "^1.3.0",
"@types/react-modal": "^3.12.1",
@ -3373,6 +3374,12 @@
"resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz",
"integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg=="
},
"node_modules/@types/dom-mediacapture-record": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/@types/dom-mediacapture-record/-/dom-mediacapture-record-1.0.10.tgz",
"integrity": "sha512-8O84hHuVhMMLHLybf3y9SQpNcnQSuzVzcJaUNq9+4Ovb7fodS0aQXep4hyMtxd6fe/dyszbHFjFqtyawf4y46A==",
"dev": true
},
"node_modules/@types/eslint": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.0.tgz",
@ -24347,6 +24354,12 @@
"resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz",
"integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg=="
},
"@types/dom-mediacapture-record": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/@types/dom-mediacapture-record/-/dom-mediacapture-record-1.0.10.tgz",
"integrity": "sha512-8O84hHuVhMMLHLybf3y9SQpNcnQSuzVzcJaUNq9+4Ovb7fodS0aQXep4hyMtxd6fe/dyszbHFjFqtyawf4y46A==",
"dev": true
},
"@types/eslint": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.0.tgz",

View File

@ -71,6 +71,7 @@
]
},
"devDependencies": {
"@types/dom-mediacapture-record": "^1.0.10",
"@types/javascript-time-ago": "^2.0.3",
"@types/promise-timeout": "^1.3.0",
"@types/react-modal": "^3.12.1",

View File

@ -142,17 +142,33 @@ const WSListener: React.FunctionComponent = () => {
dispatch(auth.updatedUser(args));
dispatch(users.updated(args));
});
ws.on('VOICE_DATA', (args) => {
alert(args);
ws.on('VOICE_DATA', async (args) => {
const channelId = args.channelId;
if (!channelId) return;
let audioChunks: Blob[] = [];
const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
const recorder = new MediaRecorder(mediaStream);
recorder.start();
recorder.onstart = () => {
audioChunks = [];
}
recorder.ondataavailable = (e) =>{
console.log('data available');
audioChunks.push(e.data);
};
recorder.onstop = () => {
const blob = new Blob(audioChunks, { 'type': 'audio/ogg; codecs=opus' });
ws.emit('VOICE_DATA', { channelId, blob });
}
setTimeout(() => recorder.stop(), 100);
});
ws.on('VOICE_STATE_UPDATE', (args) => {
const data = { userId: args.userId, partialUser: { voice: args.voice } };
dispatch(auth.updatedUser(data));
dispatch(users.updated(data ));
if (!args.voice.channelId) return;
ws.emit('VOICE_DATA', { channelId: args.voice.channelId })
dispatch(users.updated(data));
});
dispatch(meta.listenedToWS());

2
types/entity.d.ts vendored
View File

@ -92,7 +92,7 @@ declare namespace ChannelTypes {
}
export interface VoiceConnection {
userId: string;
stream: any;
blob?: Blob;
}
}

2
types/ws.d.ts vendored
View File

@ -228,6 +228,7 @@ declare namespace WS {
}
export interface VoiceData {
channelId: string;
blob?: Blob;
}
}
@ -364,6 +365,7 @@ declare namespace WS {
partialUser: Partial<UserTypes.Self>;
}
export interface VoiceData {
channelId: string;
connections: VoiceConnection[];
}
export interface VoiceStateUpdate {