fix: multiple audio track issue
This commit is contained in:
parent
686cebe577
commit
2c0f2a4a41
@ -2149,6 +2149,7 @@ function endCallForAll() {
|
||||
// --- SILENT CALL RECORDING ENGINE FOR INTERVIEWERS & ADMINS ---
|
||||
let adminMediaRecorder = null;
|
||||
let adminRecordedChunks = [];
|
||||
let recAudioContext = null;
|
||||
|
||||
function startCallRecording() {
|
||||
if (!currentInterviewId) {
|
||||
@ -2160,29 +2161,60 @@ function startCallRecording() {
|
||||
let candidateStream = (candVid && candVid.srcObject) ? candVid.srcObject : null;
|
||||
let streamToRecord = new MediaStream();
|
||||
|
||||
// Add live Candidate Video and Audio tracks
|
||||
// 1. Add Video Track (Candidate video or Interviewer fallback)
|
||||
if (candidateStream) {
|
||||
candidateStream.getTracks().forEach(track => {
|
||||
candidateStream.getVideoTracks().forEach(track => {
|
||||
if (track.readyState === 'live') {
|
||||
try { streamToRecord.addTrack(track); } catch(e) {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add Interviewer Local Microphone Audio track for 2-way call recording
|
||||
if (interviewerLocalStream) {
|
||||
interviewerLocalStream.getAudioTracks().forEach(track => {
|
||||
if (track.readyState === 'live' && !streamToRecord.getAudioTracks().includes(track)) {
|
||||
try { streamToRecord.addTrack(track); } catch(e) {}
|
||||
}
|
||||
});
|
||||
if (streamToRecord.getVideoTracks().length === 0) {
|
||||
if (streamToRecord.getVideoTracks().length === 0 && interviewerLocalStream) {
|
||||
interviewerLocalStream.getVideoTracks().forEach(track => {
|
||||
if (track.readyState === 'live') {
|
||||
try { streamToRecord.addTrack(track); } catch(e) {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 2. Mix Multiple Audio Tracks into a SINGLE Audio Track via Web Audio API
|
||||
// (MediaRecorder standard throws DOMException if streamToRecord has >1 audio track)
|
||||
const candAudioTracks = candidateStream ? candidateStream.getAudioTracks().filter(t => t.readyState === 'live') : [];
|
||||
const adminAudioTracks = interviewerLocalStream ? interviewerLocalStream.getAudioTracks().filter(t => t.readyState === 'live') : [];
|
||||
|
||||
if (candAudioTracks.length > 0 || adminAudioTracks.length > 0) {
|
||||
try {
|
||||
const AudioContextClass = window.AudioContext || window.webkitAudioContext;
|
||||
if (recAudioContext) {
|
||||
try { recAudioContext.close(); } catch(e) {}
|
||||
}
|
||||
recAudioContext = new AudioContextClass();
|
||||
const audioDestination = recAudioContext.createMediaStreamDestination();
|
||||
|
||||
if (candAudioTracks.length > 0) {
|
||||
const candAudioStream = new MediaStream(candAudioTracks);
|
||||
const candSource = recAudioContext.createMediaStreamSource(candAudioStream);
|
||||
candSource.connect(audioDestination);
|
||||
}
|
||||
|
||||
if (adminAudioTracks.length > 0) {
|
||||
const adminAudioStream = new MediaStream(adminAudioTracks);
|
||||
const adminSource = recAudioContext.createMediaStreamSource(adminAudioStream);
|
||||
adminSource.connect(audioDestination);
|
||||
}
|
||||
|
||||
const mixedAudioTrack = audioDestination.stream.getAudioTracks()[0];
|
||||
if (mixedAudioTrack) {
|
||||
streamToRecord.addTrack(mixedAudioTrack);
|
||||
}
|
||||
} catch(e) {
|
||||
console.warn('Web Audio API mixing fallback:', e);
|
||||
const fallbackAudio = candAudioTracks[0] || adminAudioTracks[0];
|
||||
if (fallbackAudio) {
|
||||
try { streamToRecord.addTrack(fallbackAudio); } catch(err) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const activeTracks = streamToRecord.getTracks().filter(t => t.readyState === 'live');
|
||||
@ -2215,6 +2247,10 @@ function startCallRecording() {
|
||||
};
|
||||
|
||||
adminMediaRecorder.onstop = function() {
|
||||
if (recAudioContext) {
|
||||
try { recAudioContext.close(); } catch(e) {}
|
||||
recAudioContext = null;
|
||||
}
|
||||
if (adminRecordedChunks.length === 0) return;
|
||||
const recMime = adminMediaRecorder.mimeType || 'video/webm';
|
||||
const isMp4 = recMime.includes('mp4');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user