• С чего лучше начать изучать новичку js?

    @historydev Куратор тега JavaScript
    Jadeis, я учился по очень старым видео, книг в моих библиотеках не было, а читать с планшета который выжигает тебе глаза было не очень продуктивно) Так что я посоветую mdn + youtube, можете глянуть Минина, только не покупайте никакие курсы у этих людей) Что бы вам не говорили)
  • Как сохранять авторизацию пользователя в куки?

    @historydev
    Никита Савченко, Посмотрите доки, напишите как получится и если что-то будет непонятно, задайте новый вопрос.
  • С чего лучше начать изучать новичку js?

    @historydev Куратор тега JavaScript
    Начните с доков на mdn, но если нет основ html/css то начните с них, пустой js никому сейчас не нужен. На счёт книг не знаю, они заложат вам гору теории полагаю, а выше перечисленное даст практику. Некоторым проще понимать что здесь происходит на практике.
  • Почему remoteDescription null?

    @historydev Автор вопроса, куратор тега JavaScript
    Сергей Сергей, Здравствуйте! Спасибо! Я нашёл рабочий исходник который работает на new BroadcastChannel('webrtc'), переписал на сокеты, сейчас разбираюсь сижу глубже:

    const socket = io('http://localhost:4000');
    
    const startButton = document.getElementById('startButton');
    const hangupButton = document.getElementById('hangupButton');
    const joinRoom = document.getElementById('joinRoom');
    
    const localVideo = document.getElementById('localVideo');
    const remoteVideo = document.getElementById('remoteVideo');
    
    joinRoom.onclick = async () => {
    	socket.emit('joinRoom', document.getElementById('companionId').value);
    }
    
    let pc;
    let localStream;
    
    const onMessage = data => {
    
    	if (!localStream) {
    		console.log('not ready yet');
    		return;
    	}
    
    	console.log(data);
    
    	switch (data.type) {
    		case 'offer':
    			handleOffer(data);
    			break;
    		case 'answer':
    			handleAnswer(data);
    			break;
    		case 'candidate':
    			handleCandidate(data);
    			break;
    		case 'ready':
    			// A second tab joined. This tab will initiate a call unless in a call already.
    			if (pc) {
    				console.log('already in call, ignoring');
    				return;
    			}
    			makeCall(data);
    			break;
    		case 'bye':
    			if (pc) {
    				hangup(data);
    			}
    			break;
    		default:
    			console.log('unhandled', data);
    			break;
    	}
    }
    
    socket.on('message', onMessage);
    
    startButton.onclick = async () => {
    
    	localStream = await navigator.mediaDevices.getUserMedia({audio: true, video: true});
    	localVideo.srcObject = localStream;
    
    	startButton.disabled = true;
    	hangupButton.disabled = false;
    
    	const companionId = document.getElementById('companionId').value;
    
    	socket.emit('message',
    		{
    			id: companionId,
    			message: {
    				type: 'ready'
    			}
    		});
    }
    
    hangupButton.onclick = async () => {
    	hangup();
    	socket.emit('message',
    		{
    			id: companionId,
    			message: {
    				type: 'bye'
    			}
    		});
    }
    
    async function hangup() {
    	if (pc) {
    		pc.close();
    		pc = null;
    	}
    	localStream.getTracks().forEach(track => track.stop());
    	localStream = null;
    	startButton.disabled = false;
    	hangupButton.disabled = true;
    }
    
    function createPeerConnection() {
    	pc = new RTCPeerConnection();
    	pc.onicecandidate = e => {
    		const message = {
    			type: 'candidate',
    			candidate: null
    		};
    		if (e.candidate) {
    			message.candidate = e.candidate.candidate;
    			message.sdpMid = e.candidate.sdpMid;
    			message.sdpMLineIndex = e.candidate.sdpMLineIndex;
    		}
    
    		const companionId = document.getElementById('companionId').value;
    
    		socket.emit('message', {
    			id: companionId,
    			message
    		});
    
    	}
    	pc.ontrack = e => remoteVideo.srcObject = e.streams[0];
    	localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
    }
    
    async function makeCall() {
    	await createPeerConnection();
    	const companionId = document.getElementById('companionId').value;
    
    	const offer = await pc.createOffer();
    	socket.emit('message', {
    		id: companionId,
    		message: {
    			type: 'offer',
    			sdp: offer.sdp
    		}
    	});
    	await pc.setLocalDescription(offer);
    }
    
    async function handleOffer(offer) {
    	if (pc) {
    		console.error('existing peerconnection');
    		return;
    	}
    	await createPeerConnection();
    	await pc.setRemoteDescription(offer);
    	const companionId = document.getElementById('companionId').value;
    
    	const answer = await pc.createAnswer();
    	socket.emit('message', {
    		id: companionId,
    		message: {
    			type: 'answer',
    			sdp: answer.sdp
    		}
    	});
    	await pc.setLocalDescription(answer);
    }
    
    async function handleAnswer(answer) {
    	if (!pc) {
    		console.error('no peerconnection');
    		return;
    	}
    	await pc.setRemoteDescription(answer);
    }
    
    async function handleCandidate(candidate) {
    
    	console.log('Candidate', candidate)
    
    	if (!pc) {
    		console.error('no peerconnection');
    		return;
    	}
    	if (!candidate.candidate) {
    
    		console.log('Candidate null');
    
    		await pc.addIceCandidate(null);
    	} else {
    		await pc.addIceCandidate(candidate);
    	}
    }


    P.S. Я оставлю ссылку на репозиторий в ответе на этот вопрос, для будущих таких как я)
  • Как настроить мой первый webRTC?

    @historydev Автор вопроса, куратор тега JavaScript
    Сергей Сергей, так мне чтобы всё работало надо что-то передать? Я пытаюсь добиться статуса подключён в обработчиках, мне всё ещё ничего оттуда не приходит:

    peerConnection.addEventListener('connectionstatechange', event => {
    
    	console.log('PeerState: ', peerConnection.connectionState)
    	if (peerConnection.connectionState === 'connected') {
    		console.log('Peer connected')
    	}
    });


    Хорошо, я попробую, спасибо!
  • Как настроить мой первый webRTC?

    @historydev Автор вопроса, куратор тега JavaScript
    Сергей Сергей, ничего не нашёл по потокам данных peerconnection, что вы имеете ввиду под ним? Нашёл только DataChannel
  • Как выполнить последовательно функцию js?

    @historydev Куратор тега JavaScript
    Дмитрий Путилов, и вернуть их из then, посмотрите что в res и что в res.data для начала
  • Как настроить мой первый webRTC?

    @historydev Автор вопроса, куратор тега JavaScript
    Сергей Сергей, разобрал на события, надеюсь так код будет более читабельным, я по прежнему не понимаю что тут происходит и что от меня хочет программа. Жму listen - жму makeCall, ничего не происходит, аналогично наоборот. Получаю ошибку только если на обоих makeCall нажать, я не понимаю как это работать должно. Подскажите пожалуйста какой слушатель поместить в обработчик listen или я что-то вообще не то делаю?

    приёмник сокетов вот:

    socket.on('message', data => {
    		console.log(data);
    		socket.emit(data.type, data.message);
    	})


    import { io } from "https://cdn.socket.io/4.3.2/socket.io.esm.min.js";
    
    const socket = io('http://localhost:4000');
    
    const pc = () => {
    	const configuration = {'iceServers': [{'urls': 'stun:stun.l.google.com:19302'}]}
    	return new RTCPeerConnection(configuration);
    }
    
    const peerConnection = pc();
    
    socket.on('answer', async answer => {
    	console.log(peerConnection.signalingState, peerConnection.connectionState)
    	const remoteDesc = new RTCSessionDescription(answer);
    	await peerConnection.setRemoteDescription(remoteDesc);
    });
    
    socket.on('iceCandidate', async iceCandidate => {
    	await peerConnection.addIceCandidate(iceCandidate);
    });
    
    peerConnection.addEventListener('icecandidate', event => {
    	console.log(event);
    	if (event.candidate) {
    		console.log('candidate')
    		socket.emit('message', {type: 'iceCandidate', message: event.candidate});
    	}
    });
    
    peerConnection.addEventListener('connectionstatechange', event => {
    
    	console.log('PeerState: ', peerConnection.connectionState)
    	if (peerConnection.connectionState === 'connected') {
    		console.log('Peer connected')
    	}
    });
    
    document.querySelector('#listen').onclick = () => {
    	socket.on('offer', async offer => {
    		await peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
    		const answer = await peerConnection.createAnswer();
    		await peerConnection.setLocalDescription(answer);
    		socket.emit('message', {type: 'answer', message: answer});
    	});
    }
    
    
    document.querySelector('#makeCall').onclick = async() => {
    	const offer = await peerConnection.createOffer();
    	await peerConnection.setLocalDescription(offer);
    	socket.emit('message', {type: 'offer', message: offer});
    }
  • Как настроить мой первый webRTC?

    @historydev Автор вопроса, куратор тега JavaScript
    Сергей Сергей, разделил, но не уверен что корректно, я создаю предложение и получаю статус have-local-offer, но ответить на него не получается:

    import { io } from "https://cdn.socket.io/4.3.2/socket.io.esm.min.js";
    
    const socket = io('http://localhost:4000');
    
    const pc = () => {
    	const configuration = {'iceServers': [{'urls': 'stun:stun.l.google.com:19302'}]}
    	return new RTCPeerConnection(configuration);
    }
    
    const peerConnection = pc();
    
    async function makeCall(state) {
    
    	socket.on('response', async message => {
    
    		console.log(message);
    
    		//console.log(peerConnection.signalingState, peerConnection.connectionState)
    
    		if (message.answer) {
    			try {
    
    				console.log(peerConnection.signalingState, peerConnection.connectionState)
    
    				console.log('not stable')
    
    				const remoteDesc = new RTCSessionDescription(message.answer);
    				await peerConnection.setRemoteDescription(remoteDesc);
    
    
    			} catch (e) {
    				console.error('Answer error', e)
    			}
    		}
    
    		if (message.offer) {
    
    			console.log(peerConnection.signalingState, peerConnection.connectionState)
    
    			try {
    				await peerConnection.setRemoteDescription(new RTCSessionDescription(message.offer));
    				const answer = await peerConnection.createAnswer();
    				await peerConnection.setLocalDescription(answer);
    				if(state) socket.emit('message', {answer});
    			} catch (e) {
    				console.error('Offer error', e)
    			}
    		}
    
    		if (message.iceCandidate) {
    			try {
    				await peerConnection.addIceCandidate(message.iceCandidate);
    			} catch (e) {
    				console.error('Error adding received ice candidate', e);
    			}
    		}
    
    	});
    	peerConnection.addEventListener('icecandidate', event => {
    		console.log(event);
    		if (event.candidate) {
    			console.log('candidate')
    			socket.emit('message', {iceCandidate: event.candidate});
    		}
    	});
    	peerConnection.addEventListener('connectionstatechange', event => {
    
    		console.log('PeerState: ', peerConnection.connectionState)
    		if (peerConnection.connectionState === 'connected') {
    			console.log('Peer connected')
    		}
    	});
    }
    
    document.querySelector('#makeCall').onclick = async() => {
    	makeCall(true);
    	console.log('wait listening')
    }
    
    document.querySelector('#listen').onclick = async() => {
    
    	makeCall(false)
    
    	console.log('start listening')
    
    	//const peerConnection = pc();
    	const offer = await peerConnection.createOffer();
    	await peerConnection.setLocalDescription(offer);
    	socket.emit('message', {offer});
    }

    Иногда проскакивает в логах сервера answer, но я не понимаю почему он там или почему его там нет
  • Как настроить мой первый webRTC?

    @historydev Автор вопроса, куратор тега JavaScript
    Сергей Сергей, хорошо, я попробую! Спасибище!
  • Как настроить мой первый webRTC?

    @historydev Автор вопроса, куратор тега JavaScript
    Сергей Сергей, после того как я получаю ответ у меня всегда stable:

    {offer: {…}}
    index.js:13 have-local-offer new
    index.js:11 {answer: {…}}
    index.js:13 stable new
    index.js:18 stable new
    index.js:20 not stable
  • Как настроить мой первый webRTC?

    @historydev Автор вопроса, куратор тега JavaScript
    Сергей Сергей, ещё у меня не отрабатывают вот эти два обработчика:

    peerConnection.addEventListener('icecandidate', event => {
    		console.log(event);
    		if (event.candidate) {
    			console.log('candidate')
    			socket.emit('message', {iceCandidate: event.candidate});
    		}
    	});
    	peerConnection.addEventListener('connectionstatechange', event => {
    
    		console.log('PeerState: ', peerConnection.connectionState)
    		if (peerConnection.connectionState === 'connected') {
    			console.log('Peer connected')
    		}
    	});
  • Как настроить мой первый webRTC?

    @historydev Автор вопроса, куратор тега JavaScript
    Сергей Сергей, я пока без видео, я просто пытаюсь добиться подключения
  • Картинка-ссылка на ютуб, вместо картинки появляется видео, как исправить?

    @historydev
    Игорь Луговской, так, нужно углубиться в превью ссылок и отключить его, вот по этому видео попробуйте отправить - получите свою картинку в виде ссылки, но превью останется.
  • Нужно ли разделять стили по страницам?

    @historydev
    какой стек у вас по фронту или вы сейчас не на фронте? Я видел разные методики, со своими пре-сетами на фронте, интересно что юзаете вы? Чем собираете?
  • Как "воскресить" убитые треки в userMedia?

    @historydev Автор вопроса, куратор тега JavaScript
    Сергей Сергей, погуглил, нашёл pause для mediaRecorder и нашёл вот здесь способ https://stackoverflow.com/questions/49934811/pause... решения вроде как, буду пробовать
  • Как "воскресить" убитые треки в userMedia?

    @historydev Автор вопроса, куратор тега JavaScript
    Сергей Сергей, честно, не знаю, могу вместо stop, pause юзать?