diff --git a/karma.conf.js b/karma.conf.js index 48d55e18..facc71af 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -57,7 +57,8 @@ module.exports = function (config) { base: 'Firefox', flags: ['-headless'], prefs: { - 'network.proxy.type': 0 + 'network.proxy.type': 0, + 'media.autoplay.default': 0 // Allow all autoplay } } }, diff --git a/spec/integration/movie.spec.ts b/spec/integration/movie.spec.ts index 9247b7b9..b14cf785 100644 --- a/spec/integration/movie.spec.ts +++ b/spec/integration/movie.spec.ts @@ -33,6 +33,36 @@ function validateVideoData (video: HTMLVideoElement) { expect(maxDiff).toBeLessThanOrEqual(5) } +/** + * Resolves to true if the audio is completely silent. + * @param audio + * @returns + */ +async function isAudioSilent (audio: HTMLAudioElement) { + // Set up audio context + const audioCtx = new AudioContext() + const source = audioCtx.createMediaElementSource(audio) + const analyser = audioCtx.createAnalyser() + source.connect(analyser) + analyser.connect(audioCtx.destination) + + // Play audio + audio.play() + if (!audio.paused) { + await new Promise(resolve => { + audio.addEventListener('pause', () => { + resolve() + }) + }) + } + + // Check if audio is silent + const bufferLength = analyser.frequencyBinCount + const dataArray = new Uint8Array(bufferLength) + analyser.getByteTimeDomainData(dataArray) + return dataArray.every(x => x === 128) +} + describe('Integration Tests ->', function () { describe('Movie', function () { let movie, canvas @@ -197,6 +227,47 @@ describe('Integration Tests ->', function () { // Clean up URL.revokeObjectURL(video.src) }) + + it('should produce audio when recording', async function () { + // Remove all existing layers (optional) + movie.layers.length = 0 + + // Add an audio layer + const audio = new Audio('/base/spec/integration/assets/layer/audio.wav') + await new Promise(resolve => { + audio.onloadeddata = resolve + }) + const layer = new etro.layer.Audio({ + source: audio, + startTime: 0 + }) + movie.layers.push(layer) + + // Record audio + const blob = await movie.record({ + frameRate: 30, + video: false, + type: 'audio/ogg' + }) + + // Make sure the audio blob is not empty + expect(blob.size).toBeGreaterThan(0) + + // Load blob into html audio element + const audioElement = document.createElement('audio') + audioElement.src = URL.createObjectURL(blob) + await new Promise(resolve => { + audioElement.addEventListener('canplaythrough', () => { + resolve() + }) + }) + + // Make sure the audio is not completely silent + expect(await isAudioSilent(audioElement)).toBe(false) + + // Clean up + URL.revokeObjectURL(audioElement.src) + }) }) describe('events ->', function () {