diff --git a/public/demos/audio.html b/public/demos/audio.html
index ea3a4fb..49e00b3 100644
--- a/public/demos/audio.html
+++ b/public/demos/audio.html
@@ -3,7 +3,6 @@
MWSE — Sesli Görüşme Demo
-
MWSE Sesli Görüşme Demo
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, max ~10–15 kişi için
- mesh topolojisi; daha fazlası için SRS entegrasyonu gerekir).
+ otomatik çift yönlü ses bağlantısı kurulur (P2P WebRTC mesh, küçük gruplar için).
Bağlanıyor…
-
diff --git a/public/demos/chat.html b/public/demos/chat.html
index 6479bab..f66ec96 100644
--- a/public/demos/chat.html
+++ b/public/demos/chat.html
@@ -3,7 +3,6 @@
MWSE — Chat Demo
-
@@ -37,111 +26,98 @@
MWSE Video Demo
Bağlanıyor…
-
+
-
diff --git a/sdk/webrtc/CanvasCompositor.js b/sdk/webrtc/CanvasCompositor.js
new file mode 100644
index 0000000..43dbb83
--- /dev/null
+++ b/sdk/webrtc/CanvasCompositor.js
@@ -0,0 +1,220 @@
+// CanvasCompositor — gelen video track'lerini tek bir canvas'ta birleştirir.
+//
+// Kullanım:
+// const comp = new CanvasCompositor({ width: 1280, height: 720, fps: 30 });
+// comp.addTrack('alice', videoTrack);
+// comp.addTrack('bob', videoTrack2);
+// comp.setLayout('grid'); // 'grid' | 'pip' | 'side-by-side' | 'focus'
+// const stream = comp.stream(); // MediaStream → StreamManager.addStream() ile gönder
+// comp.destroy(); // cleanup
+//
+// Ses için AudioContext mix bus:
+// const { ctx, dest, stream: audioStream } = MediaSources.createAudioMix();
+// ctx.createMediaStreamSource(peerAudioStream).connect(dest);
+// // audioStream'ı da StreamManager.addStream('audio-mix', audioStream) ile gönder
+export default class CanvasCompositor {
+ constructor({ width = 1280, height = 720, fps = 30, background = '#000' } = {}) {
+ this._width = width;
+ this._height = height;
+ this._fps = fps;
+ this._bg = background;
+
+ // Use OffscreenCanvas when available (no DOM required, runs in workers too).
+ if (typeof OffscreenCanvas !== 'undefined') {
+ this._canvas = new OffscreenCanvas(width, height);
+ } else {
+ this._canvas = document.createElement('canvas');
+ this._canvas.width = width;
+ this._canvas.height = height;
+ }
+ this._ctx = this._canvas.getContext('2d');
+ this._tracks = new Map(); // label → { track, video, active }
+ this._layout = 'grid';
+ this._focus = null; // label of the focused track in 'focus' mode
+ this._timer = null;
+ this._stream = null;
+
+ this._start();
+ }
+
+ // ---- Track management -----------------------------------------------
+
+ // Add a VideoTrack to the compositor. A hidden