Skip to content

Commit 0e51ee6

Browse files
authored
Revert "84 garbage decoding always fails (#85)" (#86)
This reverts commit 6b37e35.
1 parent 6b37e35 commit 0e51ee6

File tree

6 files changed

+78
-27
lines changed

6 files changed

+78
-27
lines changed

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "scribe",
33
"name": "Scribe",
4-
"version": "2.2.1",
4+
"version": "2.2.0",
55
"minAppVersion": "0.15.0",
66
"description": "Record, transcribe, and transform voice notes into structured insights. Leverage Whisper or AssemblyAI and ChatGPT to fill in gaps, generate summaries, and visualize ideas — all seamlessly integrated within Obsidian.",
77
"author": "Mike Alicea",

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "obsidian-scribe-plugin",
3-
"version": "2.2.1",
3+
"version": "2.2.0",
44
"description": "An Obsidian plugin for recording voice notes, transcribing the audio, and summarizing the text - All in one",
55
"main": "build/main.js",
66
"scripts": {
@@ -25,6 +25,8 @@
2525
"typescript": "^5.8.3"
2626
},
2727
"dependencies": {
28+
"@ffmpeg/ffmpeg": "^0.12.15",
29+
"@ffmpeg/util": "^0.12.2",
2830
"@fix-webm-duration/fix": "^1.0.1",
2931
"@langchain/core": "^0.3.40",
3032
"@langchain/openai": "^0.5.10",

src/audioRecord/audioRecord.ts

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import { Notice } from 'obsidian';
88
import { fixWebmDuration } from '@fix-webm-duration/fix';
9+
import { FFmpeg } from '@ffmpeg/ffmpeg';
10+
import { fetchFile, toBlobURL } from '@ffmpeg/util';
911

1012
import {
1113
mimeTypeToFileExtension,
@@ -23,17 +25,17 @@ export class AudioRecord {
2325
private mimeType: SupportedMimeType = pickMimeType('audio/webm; codecs=opus');
2426
private bitRate = 32000;
2527

26-
constructor(desiredFormat: 'webm' = 'webm') {
28+
constructor(desiredFormat: 'webm' | 'mp3' = 'webm') {
2729
this.desiredFormat = desiredFormat;
2830
// We always record in WebM format because it's widely supported
29-
// DEPRECATED: MP3
30-
// If MP3 is desired, we'll wait for requests for it. Our previous implementation caused issues on MacOS and iOS.
31+
// If MP3 is desired, we'll convert it later
3132
this.fileExtension = desiredFormat;
3233
}
3334

3435
async startRecording(deviceId?: string) {
35-
const audioConstraints =
36-
deviceId && deviceId !== '' ? { deviceId: { exact: deviceId } } : true;
36+
const audioConstraints = deviceId && deviceId !== ''
37+
? { deviceId: { exact: deviceId } }
38+
: true;
3739

3840
navigator.mediaDevices
3941
.getUserMedia({ audio: audioConstraints })
@@ -79,6 +81,36 @@ export class AudioRecord {
7981
this.mediaRecorder?.pause();
8082
}
8183

84+
async convertWebmToMp3(webmBlob: Blob): Promise<Blob> {
85+
try {
86+
const ffmpeg = new FFmpeg();
87+
const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd';
88+
89+
// Load FFmpeg
90+
await ffmpeg.load({
91+
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
92+
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
93+
});
94+
95+
// Write input WebM file
96+
await ffmpeg.writeFile('input.webm', await fetchFile(webmBlob));
97+
98+
// Convert WebM to MP3
99+
await ffmpeg.exec(['-i', 'input.webm', '-c:a', 'libmp3lame', '-q:a', '2', 'output.mp3']);
100+
101+
// Read the output file
102+
const data = await ffmpeg.readFile('output.mp3');
103+
104+
// Create a Blob from the output data
105+
const mp3Blob = new Blob([data], { type: 'audio/mp3' });
106+
107+
return mp3Blob;
108+
} catch (error) {
109+
console.error('Error converting WebM to MP3:', error);
110+
throw new Error(`Failed to convert WebM to MP3: ${error.message}`);
111+
}
112+
}
113+
82114
stopRecording() {
83115
return new Promise<Blob>((resolve, reject) => {
84116
if (!this.mediaRecorder || this.mediaRecorder.state === 'inactive') {
@@ -107,7 +139,19 @@ export class AudioRecord {
107139
this.mediaRecorder = null;
108140
this.startTime = null;
109141

110-
resolve(fixedBlob);
142+
// If MP3 is desired, convert the WebM blob to MP3
143+
if (this.desiredFormat === 'mp3') {
144+
try {
145+
const mp3Blob = await this.convertWebmToMp3(fixedBlob);
146+
resolve(mp3Blob);
147+
} catch (conversionError) {
148+
console.error('Error converting to MP3, falling back to WebM:', conversionError);
149+
new Notice('Scribe: Failed to convert to MP3, saving as WebM instead');
150+
resolve(fixedBlob);
151+
}
152+
} else {
153+
resolve(fixedBlob);
154+
}
111155
} catch (err) {
112156
console.log('Error during recording stop:', err);
113157
reject(err);

src/index.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,13 @@ export default class ScribePlugin extends Plugin {
229229

230230
let fixedMermaidChart: string | undefined;
231231
if (brokenMermaidChart) {
232-
const customBaseUrl = this.settings.useCustomOpenAiBaseUrl
233-
? this.settings.customOpenAiBaseUrl
232+
const customBaseUrl = this.settings.useCustomOpenAiBaseUrl
233+
? this.settings.customOpenAiBaseUrl
234234
: undefined;
235-
const customChatModel = this.settings.useCustomOpenAiBaseUrl
236-
? this.settings.customChatModel
235+
const customChatModel = this.settings.useCustomOpenAiBaseUrl
236+
? this.settings.customChatModel
237237
: undefined;
238-
238+
239239
fixedMermaidChart = (
240240
await llmFixMermaidChart(
241241
this.settings.openAiApiKey,
@@ -402,10 +402,12 @@ export default class ScribePlugin extends Plugin {
402402
) {
403403
try {
404404
if (this.settings.isDisableLlmTranscription) {
405-
new Notice('Scribe: 🎧 Transcription is disabled in settings');
406-
return '';
405+
new Notice(
406+
`Scribe: 🎧 Transcription is disabled in settings`,
407+
);
408+
return "";
407409
}
408-
410+
409411
new Notice(
410412
`Scribe: 🎧 Beginning transcription w/ ${this.settings.transcriptPlatform}`,
411413
);
@@ -420,11 +422,11 @@ export default class ScribePlugin extends Plugin {
420422
this.settings.openAiApiKey,
421423
audioBuffer,
422424
scribeOptions,
423-
this.settings.useCustomOpenAiBaseUrl
424-
? this.settings.customOpenAiBaseUrl
425+
this.settings.useCustomOpenAiBaseUrl
426+
? this.settings.customOpenAiBaseUrl
425427
: undefined,
426-
this.settings.useCustomOpenAiBaseUrl
427-
? this.settings.customTranscriptModel
428+
this.settings.useCustomOpenAiBaseUrl
429+
? this.settings.customTranscriptModel
428430
: undefined,
429431
);
430432

@@ -451,11 +453,11 @@ export default class ScribePlugin extends Plugin {
451453
) {
452454
new Notice('Scribe: 🧠 Sending to LLM to summarize');
453455

454-
const customBaseUrl = this.settings.useCustomOpenAiBaseUrl
455-
? this.settings.customOpenAiBaseUrl
456+
const customBaseUrl = this.settings.useCustomOpenAiBaseUrl
457+
? this.settings.customOpenAiBaseUrl
456458
: undefined;
457-
const customChatModel = this.settings.useCustomOpenAiBaseUrl
458-
? this.settings.customChatModel
459+
const customChatModel = this.settings.useCustomOpenAiBaseUrl
460+
? this.settings.customChatModel
459461
: undefined;
460462

461463
const llmSummary = await summarizeTranscript(

src/settings/GeneralSettingsTab.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,16 @@ function GeneralSettingsTab() {
9696
<SettingsSelect
9797
{...register('audioFileFormat')}
9898
name="Audio file format"
99-
description="Choose the format for saving audio recordings. We currently only support WebM. MP3 is deprecated due to issues on MacOS and iOS."
100-
// DEPRECATED: MP3 — If MP3 is desired, we'll wait for requests for it. Our previous implementation caused issues on MacOS and iOS.
99+
description="Choose the format for saving audio recordings. MP3 format will be converted from WebM on the client side."
101100
valuesMapping={[
102101
{
103102
value: 'webm',
104103
displayName: 'WebM',
105104
},
105+
{
106+
value: 'mp3',
107+
displayName: 'MP3',
108+
},
106109
]}
107110
/>
108111
<SettingsItemHeader name="File names settings" />

src/settings/settings.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export interface ScribePluginSettings {
4848
noteTemplates: ScribeTemplate[];
4949
isFrontMatterLinkToScribe: boolean;
5050
selectedAudioDeviceId: string;
51-
audioFileFormat: 'webm';
51+
audioFileFormat: 'webm' | 'mp3';
5252
// Custom OpenAI settings
5353
useCustomOpenAiBaseUrl: boolean;
5454
customOpenAiBaseUrl: string;

0 commit comments

Comments
 (0)