Я новичок, пытаюсь создать приложение для видеозвонков webRTC в качестве проекта (мне удалось заставить его работать с веб-сокетами, но при медленном Интернете оно зависает). Я использую Angular для FE и Go для BE. У меня проблема с тем, что обратный вызов PeerConnection.onicecandidate не срабатывает. Методы setLocalDescription и setRemoteDescription, похоже, не выдают никаких ошибок, а регистрация SDP выглядит нормально, поэтому проблема вряд ли связана с серверной частью, поскольку предложения и ответы SDP передаются правильно (через веб-сокеты). Вот код службы Angular, который должен обеспечить подключение:
import { HttpClient, HttpHeaders } from '@angular/common/http'
import { Injectable, OnInit } from '@angular/core'
import { from, lastValueFrom, Observable } from 'rxjs'
import { Router } from '@angular/router';
interface Member {
memberID: string
name: string
conn: RTCPeerConnection | null
}
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private http: HttpClient, private router: Router) { }
// members data
public stableMembers: Member[] = []
// private httpUrl = 'https://callgo-server-386137910114.europe-west1.run.app'
// private webSocketUrl = 'wss://callgo-server-386137910114.europe-west1.run.app/ws'
private httpUrl = 'http://localhost:8080'
private webSocketUrl = 'http://localhost:8080/ws'
// http
createSession(): Promise {
return lastValueFrom(this.http.post(`${this.httpUrl}/initialize`, null))
}
kickSession(sessionID: string, memberID: string, password: string): Promise {
return lastValueFrom(this.http.post(`${this.httpUrl}/disconnect`, {
"sessionID":`${sessionID}`,
"memberID":`${memberID}`,
"password":`${password}`
}))
}
// websocket
private webSocket!: WebSocket
// stun server
private config = {iceServers: [{ urls: ['stun:stun.l.google.com:19302', 'stun:stun2.1.google.com:19302'] }]}
// callbacks that other classes can define using their context, but apiService calls them
public initMemberDisplay = (newMember: Member) => {}
public initMemberCamera = (newMember: Member) => {}
async connect(sessionID: string, displayName: string) {
console.log(sessionID)
this.webSocket = new WebSocket(`${this.webSocketUrl}?sessionID=${sessionID}&displayName=${displayName}`)
this.webSocket.onopen = (event: Event) => {
console.log('WebSocket connection established')
}
this.webSocket.onmessage = async (message: MessageEvent) => {
const data = JSON.parse(message.data)
// when being asigned an ID
if(data.type == "assignID") {
sessionStorage.setItem("myID", data.memberID)
this.stableMembers.push({
"name": data.memberName,
"memberID": data.memberID,
"conn": null
})
}
// when being notified about who is already in the meeting (on meeting join)
if(data.type == "exist") {
this.stableMembers.push({
"name": data.memberName,
"memberID": data.memberID,
"conn": null
})
}
// when being notified about a new joining member
if(data.type == "join") {
// webRTC
const peerConnection = new RTCPeerConnection(this.config)
// send ICE
peerConnection.onicecandidate = (event: RTCPeerConnectionIceEvent) => {
console.log(event)
event.candidate && console.log(event.candidate)
}
// send SDP
try {
await peerConnection.setLocalDescription(await peerConnection.createOffer())
this.sendSDP(peerConnection.localDescription!, data.memberID, sessionStorage.getItem("myID")!)
} catch(error) {
console.log(error)
}
this.stableMembers.push({
"name": data.memberName,
"memberID": data.memberID,
"conn": peerConnection
})
}
// on member disconnect notification
if(data.type == "leave") {
this.stableMembers = this.stableMembers.filter(member => member.memberID != data.memberID)
}
// on received SDP
if(data.sdp) {
if(data.sdp.type == "offer") {
const peerConnection = new RTCPeerConnection(this.config)
try {
const findWithSameID = this.stableMembers.find(member => member?.memberID == data?.from)
findWithSameID!.conn = peerConnection
await peerConnection.setRemoteDescription(new RTCSessionDescription(data.sdp))
const answer: RTCSessionDescriptionInit = await peerConnection.createAnswer()
await peerConnection.setLocalDescription(answer)
this.sendSDP(answer, data.from, sessionStorage.getItem("myID")!)
this.initMemberDisplay(findWithSameID!)
this.initMemberCamera(findWithSameID!)
} catch(error) {
console.log(error)
}
}
if(data.sdp.type == "answer") {
try {
const findWithSameID = this.stableMembers.find(member => member?.memberID == data?.from)
await findWithSameID!.conn!.setRemoteDescription(new RTCSessionDescription(data.sdp))
this.initMemberDisplay(findWithSameID!)
this.initMemberCamera(findWithSameID!)
} catch(error) {
console.log(error)
}
}
}
}
this.webSocket.onclose = () => {
console.log('WebSocket connection closed')
this.stableMembers = []
this.router.navigate(['/menu'])
}
this.webSocket.onerror = (error) => {
console.error('WebSocket error:', error)
}
}
close() {
if(this.webSocket && this.webSocket.readyState === WebSocket.OPEN) {
this.webSocket.close()
} else {
console.error('WebSocket already closed.')
}
}
sendSDP(sdp: RTCSessionDescriptionInit, to: string, from: string) {
this.webSocket.send(JSON.stringify({
"to": to,
"from": from,
"sdp": sdp
}))
}
}
В качестве краткого объяснения: стабильный элемент хранит ссылки на все члены клиента, а остальная часть кода изменяет его по мере необходимости. Предполагается, что обратные вызовы initMemberDisplay и initMemberCamera определяются другими компонентами и используются для обработки приема и отправки видеодорожек. Я еще не реализовал ничего, связанного с ICE, ни в FE, ни в BE, но, пытаясь это сделать, я заметил, что обратный вызов onicecandidate просто не будет вызываться. Я использую бесплатные известные оглушающие серверы Google: Private config = {iceServers: [{ urls: ['stun:stun.l.google.com:19302', 'stun:stun2.1.google.com:19302'] } ]}. Если вы хотите прочитать остальную часть кода, репозиторий находится здесь: https://github.com/HoriaBosoanca/callgo-client. В файле readme есть ссылка на код BE.
Я попробовал зарегистрировать событие из обратного вызова PeerConnection.onicecandidate = (event: RTCPeerConnectionIceEvent) => {console.log(event)} и я заметил, что ничего не было зарегистрировано.
Я новичок, пытаюсь создать приложение для видеозвонков webRTC в качестве проекта (мне удалось заставить его работать с веб-сокетами, но при медленном Интернете оно зависает). Я использую Angular для FE и Go для BE. У меня проблема с тем, что обратный вызов PeerConnection.onicecandidate не срабатывает. Методы setLocalDescription и setRemoteDescription, похоже, не выдают никаких ошибок, а регистрация SDP выглядит нормально, поэтому проблема вряд ли связана с серверной частью, поскольку предложения и ответы SDP передаются правильно (через веб-сокеты). Вот код службы Angular, который должен обеспечить подключение: [code]import { HttpClient, HttpHeaders } from '@angular/common/http' import { Injectable, OnInit } from '@angular/core' import { from, lastValueFrom, Observable } from 'rxjs' import { Router } from '@angular/router';
// callbacks that other classes can define using their context, but apiService calls them public initMemberDisplay = (newMember: Member) => {} public initMemberCamera = (newMember: Member) => {}
// when being asigned an ID if(data.type == "assignID") { sessionStorage.setItem("myID", data.memberID) this.stableMembers.push({ "name": data.memberName, "memberID": data.memberID, "conn": null }) }
// when being notified about who is already in the meeting (on meeting join) if(data.type == "exist") { this.stableMembers.push({ "name": data.memberName, "memberID": data.memberID, "conn": null }) }
// when being notified about a new joining member if(data.type == "join") { // webRTC const peerConnection = new RTCPeerConnection(this.config) // send ICE peerConnection.onicecandidate = (event: RTCPeerConnectionIceEvent) => { console.log(event) event.candidate && console.log(event.candidate) } // send SDP try { await peerConnection.setLocalDescription(await peerConnection.createOffer()) this.sendSDP(peerConnection.localDescription!, data.memberID, sessionStorage.getItem("myID")!) } catch(error) { console.log(error) }
sendSDP(sdp: RTCSessionDescriptionInit, to: string, from: string) { this.webSocket.send(JSON.stringify({ "to": to, "from": from, "sdp": sdp })) }
} [/code] В качестве краткого объяснения: стабильный элемент хранит ссылки на все члены клиента, а остальная часть кода изменяет его по мере необходимости. Предполагается, что обратные вызовы initMemberDisplay и initMemberCamera определяются другими компонентами и используются для обработки приема и отправки видеодорожек. Я еще не реализовал ничего, связанного с ICE, ни в FE, ни в BE, но, пытаясь это сделать, я заметил, что обратный вызов onicecandidate просто не будет вызываться. Я использую бесплатные известные оглушающие серверы Google: Private config = {iceServers: [{ urls: ['stun:stun.l.google.com:19302', 'stun:stun2.1.google.com:19302'] } ]}. Если вы хотите прочитать остальную часть кода, репозиторий находится здесь: https://github.com/HoriaBosoanca/callgo-client. В файле readme есть ссылка на код BE. Я попробовал зарегистрировать событие из обратного вызова PeerConnection.onicecandidate = (event: RTCPeerConnectionIceEvent) => {console.log(event)} и я заметил, что ничего не было зарегистрировано.
Я создаю приложение для голосовых/видеозвонков на Android с использованием WebRTC, где кандидаты SDP и ICE обмениваются через сервер WebSocket. Поток кандидатов SDP и ICE между двумя пользователями (A и B) выглядит правильно в журналах WebSocket, но...
Я создаю приложение для голосовых/видеозвонков на Android с использованием WebRTC, где кандидаты SDP и ICE обмениваются через сервер WebSocket. Поток кандидатов SDP и ICE между двумя пользователями (A и B) выглядит правильно в журналах WebSocket, но...
Я создаю приложение Android Assirod с открытым исходным кодом, которое использует сервер node.js в качестве моста в API Google Gemini. Приложение использует WEBRTC для потоковой передачи звука в реальном времени между клиентом Android и сервером....
Я успешно применил пользовательскую цветовую палитру с Material 3 и Angular Material Experimental, но продолжаю получать предупреждение в консоли: «Не удалось найти основную тему Angular Material. Большинство компонентов Material могут работать не...
Раньше управление подавлением акустического эха и автоматической регулировкой усиления на основе WebRTC было доступно через статические методы в классе WebRtcAudioUtils Google WebRTC для Android:...