Voice fix: clone TTS track to prevent Teams from killing it via track.stop()

Made-with: Cursor
This commit is contained in:
ValueOn AG 2026-02-27 13:32:08 +01:00
parent 7c00e31cfa
commit 7e62c2fc65

View file

@ -62,8 +62,8 @@ export class AudioProcedure {
// Build a new stream: our TTS audio track + their video tracks // Build a new stream: our TTS audio track + their video tracks
const combinedStream = new MediaStream(); const combinedStream = new MediaStream();
// Add our controlled audio track (TTS will be piped here) // Clone the TTS track so Teams can't kill the original via track.stop()
streamDest.stream.getAudioTracks().forEach(t => combinedStream.addTrack(t)); streamDest.stream.getAudioTracks().forEach(t => combinedStream.addTrack(t.clone()));
// Keep the real video tracks (from fake camera) // Keep the real video tracks (from fake camera)
realStream.getVideoTracks().forEach(t => combinedStream.addTrack(t)); realStream.getVideoTracks().forEach(t => combinedStream.addTrack(t));
@ -114,14 +114,15 @@ export class AudioProcedure {
// #region agent log // #region agent log
diag.beforeSenderTrackIds.push(sender.track.id); diag.beforeSenderTrackIds.push(sender.track.id);
// #endregion // #endregion
await sender.replaceTrack(ttsTrack); const freshClone = ttsTrack.clone();
await sender.replaceTrack(freshClone);
replaced++; replaced++;
// #region agent log // #region agent log
const afterTrack = sender.track; const afterTrack = sender.track;
diag.afterSenderTrackIds.push(afterTrack?.id || 'null'); diag.afterSenderTrackIds.push(afterTrack?.id || 'null');
diag.afterSenderTrackEnabled = afterTrack?.enabled; diag.afterSenderTrackEnabled = afterTrack?.enabled;
diag.afterSenderTrackReadyState = afterTrack?.readyState; diag.afterSenderTrackReadyState = afterTrack?.readyState;
// Force track enabled just in case diag.originalTrackState = ttsTrack.readyState;
if (afterTrack && !afterTrack.enabled) { if (afterTrack && !afterTrack.enabled) {
afterTrack.enabled = true; afterTrack.enabled = true;
diag.forcedEnabled = true; diag.forcedEnabled = true;