fix some issues with audio recording and playback in safari #121, #122

This commit is contained in:
or-else
2023-04-14 17:47:35 -07:00
parent 6273b3287f
commit 8dd32a341b
27 changed files with 172 additions and 43 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+8 -7
View File
@@ -3589,7 +3589,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "PACKAGE_VERSION": () => (/* binding */ PACKAGE_VERSION)
/* harmony export */ });
const PACKAGE_VERSION = "0.22.2";
const PACKAGE_VERSION = "0.22.3";
/***/ }),
@@ -7596,7 +7596,7 @@ class TinodeWeb extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component)
}).then(token => {
if (token) {
return token;
} else {
} else if (typeof Notification != 'undefined') {
return Notification.requestPermission().then(permission => {
if (permission === 'granted') {
return (0,firebase_messaging__WEBPACK_IMPORTED_MODULE_3__.getToken)(fcm, {
@@ -7614,6 +7614,7 @@ class TinodeWeb extends (react__WEBPACK_IMPORTED_MODULE_0___default().Component)
}
});
}
throw new Error("Notifications are not supported");
});
}
handleResize() {
@@ -9576,7 +9577,7 @@ class AudioPlayer extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComp
}
componentWillUnmount() {
if (this.audioPlayer) {
this.audioPlayer.oncanplay = null;
this.audioPlayer.onloadedmetadata = null;
this.audioPlayer.ontimeupdate = null;
this.audioPlayer.onended = null;
this.audioPlayer.pause();
@@ -9599,7 +9600,7 @@ class AudioPlayer extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComp
}
initAudio() {
this.audioPlayer = new Audio(this.props.src);
this.audioPlayer.oncanplay = _ => this.setState({
this.audioPlayer.onloadedmetadata = _ => this.setState({
canPlay: true
});
this.audioPlayer.ontimeupdate = _ => this.setState({
@@ -9642,7 +9643,7 @@ class AudioPlayer extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComp
this.canvasContext.strokeStyle = BAR_COLOR_DARK;
for (let i = 0; i < this.viewBuffer.length; i++) {
let x = 1 + i * (LINE_WIDTH + SPACING) + LINE_WIDTH * 0.5;
let y = this.viewBuffer[i] * height * 0.9;
let y = Math.max(this.viewBuffer[i] * height * 0.9, 1);
const color = x < thumbAt ? BAR_COLOR_DARK : BAR_COLOR;
if (this.canvasContext.strokeStyle != color) {
this.canvasContext.stroke();
@@ -9650,7 +9651,7 @@ class AudioPlayer extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComp
this.canvasContext.strokeStyle = color;
}
this.canvasContext.moveTo(x, (height - y) * 0.5);
this.canvasContext.lineTo(x, height * 0.5 + y * 0.5);
this.canvasContext.lineTo(x, (height + y) * 0.5);
}
this.canvasContext.stroke();
if (this.props.duration) {
@@ -9701,7 +9702,7 @@ class AudioPlayer extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComp
this.setState({
playing: false
});
} else {
} else if (this.audioPlayer.readyState >= 2) {
this.audioPlayer.play();
this.setState({
playing: true
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+37 -9
View File
@@ -37,7 +37,9 @@ const BAR_COLOR = '#BBBD';
const BAR_SCALE = 64.0;
const VISUALIZATION_BARS = 96;
const MAX_SAMPLES_PER_BAR = 10;
const AUDIO_MIME_TYPE = 'audio/webm';
const DEFAULT_AUDIO_MIME_TYPE = 'audio/webm';
const SAFARI_AUDIO_MIME_TYPE = 'audio/mp4';
const AUDIO_MIME_TYPES = [DEFAULT_AUDIO_MIME_TYPE, SAFARI_AUDIO_MIME_TYPE, ''];
const messages = (0,react_intl__WEBPACK_IMPORTED_MODULE_1__.defineMessages)({
icon_title_delete: {
id: "icon_title_delete",
@@ -66,6 +68,13 @@ const messages = (0,react_intl__WEBPACK_IMPORTED_MODULE_1__.defineMessages)({
"type": 0,
"value": "Send message"
}]
},
failed_to_init_audio: {
id: "failed_to_init_audio",
defaultMessage: [{
"type": 0,
"value": "Failed to initialize audio recording"
}]
}
});
class AudioRecorder extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComponent) {
@@ -170,9 +179,9 @@ class AudioRecorder extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCo
this.canvasContext.beginPath();
for (let i = 0; i < this.viewBuffer.length; i++) {
let x = i * (LINE_WIDTH + SPACING) - dx;
let y = Math.min(this.viewBuffer[i] / BAR_SCALE, 0.9) * height;
let y = Math.max(Math.min(this.viewBuffer[i] / BAR_SCALE, 0.9) * height, 1);
this.canvasContext.moveTo(x, (height - y) * 0.5);
this.canvasContext.lineTo(x, height * 0.5 + y * 0.5);
this.canvasContext.lineTo(x, (height + y) * 0.5);
}
this.canvasContext.stroke();
const now = new Date().getTime();
@@ -237,12 +246,28 @@ class AudioRecorder extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCo
}
initMediaRecording(stream) {
this.stream = stream;
this.mediaRecorder = new MediaRecorder(stream, {
mimeType: AUDIO_MIME_TYPE,
audioBitsPerSecond: 24_000
AUDIO_MIME_TYPES.some(mimeType => {
if (MediaRecorder.isTypeSupported(mimeType)) {
this.mediaRecorder = new MediaRecorder(stream, {
mimeType: mimeType,
audioBitsPerSecond: 24_000
});
return true;
}
return false;
});
if (!this.mediaRecorder) {
console.warn('MediaRecorder failed to initialize: no supported audio formats');
this.props.onError(this.props.intl.formatMessage(messages.failed_to_init_audio));
return;
}
this.audioContext = new AudioContext();
this.audioInput = this.audioContext.createMediaStreamSource(stream);
if (!this.audioInput) {
console.warn('createMediaStreamSource returned null: audio input unavailable');
this.props.onError(this.props.intl.formatMessage(messages.failed_to_init_audio));
return;
}
this.analyser = this.audioContext.createAnalyser();
this.analyser.fftSize = BUFFER_SIZE;
this.audioInput.connect(this.analyser);
@@ -275,11 +300,12 @@ class AudioRecorder extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCo
this.recordingTimestamp = this.startedOn;
}
getRecording(mimeType) {
mimeType = mimeType || AUDIO_MIME_TYPE;
mimeType = mimeType || DEFAULT_AUDIO_MIME_TYPE;
let blob = new Blob(this.audioChunks, {
type: mimeType
});
return webm_duration_fix__WEBPACK_IMPORTED_MODULE_3___default()(blob, mimeType).then(fixedBlob => {
const result = mimeType == DEFAULT_AUDIO_MIME_TYPE ? webm_duration_fix__WEBPACK_IMPORTED_MODULE_3___default()(blob, mimeType) : Promise.resolve(blob);
return result.then(fixedBlob => {
blob = fixedBlob;
return fixedBlob.arrayBuffer();
}).then(arrayBuff => this.audioContext.decodeAudioData(arrayBuff)).then(decoded => this.createPreview(decoded)).then(preview => ({
@@ -311,7 +337,9 @@ class AudioRecorder extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureCo
return buffer;
}
cleanUp() {
this.audioInput.disconnect();
if (this.audioInput) {
this.audioInput.disconnect();
}
this.stream.getTracks().forEach(track => track.stop());
}
render() {
File diff suppressed because one or more lines are too long