109 lines
3.7 KiB
HTML
109 lines
3.7 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="tr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>MWSE — Sesli Görüşme Demo</title>
|
||
<style>
|
||
body { font-family: sans-serif; max-width: 700px; margin: 2rem auto; padding: 0 1rem; }
|
||
h2 { margin-bottom: .3rem; }
|
||
.note { font-size: .85rem; color: #666; margin-bottom: 1rem; }
|
||
#status { padding: 6px 10px; background: #f5f5f5; border-radius: 4px;
|
||
font-size: .9rem; margin-bottom: 1rem; }
|
||
#peers { display: flex; flex-wrap: wrap; gap: 10px; }
|
||
.peer-card { border: 1px solid #bbb; border-radius: 6px; padding: 10px 14px;
|
||
min-width: 160px; background: #fff; }
|
||
.peer-card .id { font-family: monospace; font-size: .8rem; color: #555; }
|
||
.peer-card .st { font-size: .85rem; margin-top: 4px; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h2>MWSE Sesli Görüşme Demo</h2>
|
||
<p class="note">
|
||
Aynı anda birden fazla sekme ya da kullanıcı açın. Odaya katılan herkese
|
||
otomatik çift yönlü ses bağlantısı kurulur (P2P WebRTC mesh, küçük gruplar için).
|
||
</p>
|
||
<div id="status">Bağlanıyor…</div>
|
||
<div id="peers"></div>
|
||
|
||
<script type="module">
|
||
import MWSE from '/sdk/index.js';
|
||
|
||
const mwse = new MWSE();
|
||
let localStream;
|
||
const cards = {};
|
||
|
||
mwse.on('scope', async () => {
|
||
setStatus(`Bağlandı: ${mwse.me.socketId}`);
|
||
|
||
try {
|
||
localStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||
} catch (err) {
|
||
setStatus(`Mikrofon erişimi reddedildi: ${err.message}`);
|
||
return;
|
||
}
|
||
|
||
const room = mwse.room({ name: 'sesli', joinType: 'free', ifexistsJoin: true });
|
||
await room.createRoom();
|
||
setStatus(`Odada: sesli | Kimliğim: ${mwse.me.socketId}`);
|
||
|
||
// Odaya yeni biri katıldığında — biz eşleme isteği atalım.
|
||
room.on('join', async peer => {
|
||
upsertCard(peer.socketId, 'eşleniyor…');
|
||
await peer.requestPair();
|
||
});
|
||
|
||
// Bize gelen eşleme isteğini otomatik kabul et.
|
||
mwse.me.on('request/pair', async peer => {
|
||
upsertCard(peer.socketId, 'eşleniyor…');
|
||
await peer.acceptPair();
|
||
});
|
||
|
||
// Eşleme kabul edildiğinde — WebRTC sesini başlat.
|
||
mwse.me.on('accepted/pair', peer => startAudio(peer));
|
||
mwse.me.on('end/pair', (id) => upsertCard(id, 'ayrıldı'));
|
||
});
|
||
|
||
function startAudio(peer) {
|
||
upsertCard(peer.socketId, 'bağlanıyor…');
|
||
const rtc = peer.rtc;
|
||
|
||
// Politeness: lexicographic comparison so exactly one side is polite.
|
||
const polite = mwse.me.socketId < peer.socketId;
|
||
rtc.connect({ polite });
|
||
|
||
// Mikrofon akışını gönder.
|
||
if (localStream) rtc.addStream('mic', localStream);
|
||
|
||
// Gelen ses track'lerini çal.
|
||
rtc.on('track', (track) => {
|
||
if (track.kind !== 'audio') return;
|
||
const audio = new Audio();
|
||
audio.autoplay = true;
|
||
audio.srcObject = new MediaStream([track]);
|
||
document.body.appendChild(audio);
|
||
upsertCard(peer.socketId, '🔊 konuşuyor');
|
||
});
|
||
|
||
rtc.on('connected', () => upsertCard(peer.socketId, '🟢 bağlandı'));
|
||
rtc.on('disconnected', () => upsertCard(peer.socketId, '🔴 kesildi'));
|
||
rtc.on('failed', () => upsertCard(peer.socketId, '⚠️ başarısız'));
|
||
}
|
||
|
||
function upsertCard(id, state) {
|
||
if (!cards[id]) {
|
||
const card = document.createElement('div');
|
||
card.className = 'peer-card';
|
||
card.innerHTML = `<div class="id">${id}</div><div class="st"></div>`;
|
||
document.getElementById('peers').appendChild(card);
|
||
cards[id] = card;
|
||
}
|
||
cards[id].querySelector('.st').textContent = state;
|
||
}
|
||
|
||
function setStatus(msg) {
|
||
document.getElementById('status').textContent = msg;
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|