The size of audio file is always constant number after getting it from server on Safari

Viewed 92

I am writing service for recording audio. After recording, I send it to API and when user clicks "Play" button, I get that audio file from API and play it. But for some reason, if I record that audio in Safari, after saving in API and getting it, it plays only 1 second of the whole audio, because its size is always constant number - 8683. In Chrome everything works fine.

I should also add that after recording, I can successfully play it. The problem occurs only after saving the record.

Here is my audio recording service:

export class VoiceRecorder {
    public recording: boolean = false;

    private stream: MediaStream;
    // @ts-ignore
    private mediaRecorder: MediaRecorder;
    // @ts-ignore
    private audioChunks: BlobPart[] = [];

    public start(): Observable<void> {
        this.recording = true;
        this.audioChunks = [];
        return new Observable(observer => {
            navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
                this.stream = stream
                // @ts-ignore
                this.mediaRecorder = new MediaRecorder(this.stream);
                // @ts-ignore
                this.mediaRecorder.addEventListener("dataavailable", (event: BlobEvent) => {
                    this.audioChunks.push(event.data);
                });
                this.mediaRecorder.start();
                observer.next();
                observer.complete();
            }, (error: DOMException) => {
                this.recording = false;
                observer.error(error.message);
                observer.complete();
            });
        });
    }

    public stop(): Observable<IVoiceFile> {
        if (this.mediaRecorder.state === 'inactive') {
            return of(null);
        }
        return new Observable<IVoiceFile>(observer => {
            this.mediaRecorder.addEventListener("stop", () => {
                const audioBlob = new Blob(this.audioChunks, { type: 'audio/mpeg' });
                const audioUrl = URL.createObjectURL(audioBlob);
                const audio = new Audio(audioUrl);
                this.stream.getTracks().forEach(track => track.stop());
                observer.next({ audioBlob, audioUrl });
                this.mediaRecorder = null;
                this.stream = null;
                this.recording = false;
                observer.complete();
            });
            this.mediaRecorder.stop();
        });
    }
}

I have already tried to change audio formats (audio/ogg, audio/weba, audio/webm, audio/mp3, audio/aac, audio/acc), but without success.

Any thoughts?

1 Answers

It looks to me like your dataavailable handler is not getting invoked often enough.

Try using a time interval in .start(), like this. 500 requests an invocation every 500ms.

 this.mediaRecorder.start(500);

And make sure your dataavaiable handler gets invoked repeatedly. It may not get invoked every half-second, but it should be called multiple times.

And, call this:

this.mediaRecorder.requestData();

right before you stop recording to make sure you get the last chunk of recorded data.

All that being said, Safari's implementation of this media stuff lags behind Chrome's.

Related