Skip to content

Commit

Permalink
Fix desktop audio recording
Browse files Browse the repository at this point in the history
With this, Studio pre-mixes all the audio tracks
from all the recordings, i.e. desktop and mic,
pre-mixes them and uses the resulting single audio track
in the videos that are uploaded to Opencast,
and those the user can download.

This also works in the review step.
  • Loading branch information
JulianKniephoff committed Nov 20, 2023
1 parent b709395 commit 31a37a4
Showing 1 changed file with 28 additions and 44 deletions.
72 changes: 28 additions & 44 deletions src/steps/recording/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,36 +36,29 @@ const addRecordOnStop = (
};
};

const mixAudioIntoBothVideos = (audioStream: MediaStream | null, videoStream: MediaStream) => {
if (videoStream.getAudioTracks().length) {
return videoStream;
}

if (!(audioStream?.getAudioTracks().length)) {
return videoStream;
}

return new MediaStream([...videoStream.getVideoTracks(), ...audioStream.getAudioTracks()]);
};

const mixAudioIntoVideo = (audioStream: MediaStream | null, videoStream: MediaStream) => {
if (!(audioStream?.getAudioTracks().length)) {
return videoStream;
}

if (videoStream?.getAudioTracks().length) {
const audioContext = new AudioContext();
const desktopAudio = audioContext.createMediaStreamSource(videoStream);
const micAudio = audioContext.createMediaStreamSource(audioStream);
const dest = audioContext.createMediaStreamDestination();
desktopAudio.connect(dest);
micAudio.connect(dest);

return new MediaStream([...videoStream.getVideoTracks(), ...dest.stream.getAudioTracks()]);
}

return new MediaStream([...videoStream.getVideoTracks(), ...audioStream.getAudioTracks()]);
};
const mixAudioIntoVideo = (audioStreams: (MediaStream | null)[], videoStream: MediaStream) => (
audioStreams.reduce<MediaStream>(
(stream, audioStream) => audioStream?.getAudioTracks().length
? new MediaStream([
...stream.getVideoTracks(),
...(
stream.getAudioTracks().length
? (() => {
const audioContext = new AudioContext();
const accumulatedAudio = audioContext.createMediaStreamSource(stream);
const currentAudio = audioContext.createMediaStreamSource(audioStream);
const resultAudio = audioContext.createMediaStreamDestination();
accumulatedAudio.connect(resultAudio);
currentAudio.connect(resultAudio);
return resultAudio.stream;
})()
: audioStream
).getAudioTracks(),
])
: stream,
videoStream,
)
);


export const Recording: React.FC<StepProps> = ({ goToNextStep, goToPrevStep }) => {
Expand All @@ -92,24 +85,15 @@ export const Recording: React.FC<StepProps> = ({ goToNextStep, goToPrevStep }) =
// sure, in case of a bug elsewhere, we clear the recordings here.
dispatch({ type: "CLEAR_RECORDINGS" });

if (displayStream && userStream) {
const onStopDesktop = addRecordOnStop(dispatch, "desktop");
const onStopCamera = addRecordOnStop(dispatch, "video");
const desktopStream = mixAudioIntoBothVideos(state.audioStream, displayStream);
const cameraStream = mixAudioIntoBothVideos(state.audioStream, userStream);

desktopRecorder.current = new Recorder(desktopStream, settings.recording, onStopDesktop);
desktopRecorder.current.start();
videoRecorder.current = new Recorder(cameraStream, settings.recording, onStopCamera);
videoRecorder.current.start();
} else if (displayStream) {
if (displayStream) {
const onStop = addRecordOnStop(dispatch, "desktop");
const stream = mixAudioIntoVideo(state.audioStream, displayStream);
const stream = mixAudioIntoVideo([state.audioStream], displayStream);
desktopRecorder.current = new Recorder(stream, settings.recording, onStop);
desktopRecorder.current.start();
} else if (userStream) {
}
if (userStream) {
const onStop = addRecordOnStop(dispatch, "video");
const stream = mixAudioIntoVideo(state.audioStream, userStream);
const stream = mixAudioIntoVideo([state.audioStream, displayStream], userStream);
videoRecorder.current = new Recorder(stream, settings.recording, onStop);
videoRecorder.current.start();
}
Expand Down

0 comments on commit 31a37a4

Please sign in to comment.