6 feature request allow the user to opt out of saving the audio file (#15)

* Adds options for isSaveAudioFileActive

* Optionally add to frontmatter

* Enables deleting the audio file after scribe

* Sets the default for transcribe & save audio file from settings

* Adds the default recording options that can be set in settings

* Bumps version!
This commit is contained in:
Mike A 2025-01-28 10:16:56 -05:00 committed by GitHub
parent f5133ca6c6
commit 648803cc28
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 86 additions and 33 deletions

BIN
logos/scribe-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 KiB

View file

@ -1,7 +1,7 @@
{
"id": "scribe",
"name": "Scribe",
"version": "1.0.9",
"version": "1.1.0",
"minAppVersion": "0.15.0",
"description": "Record voice notes, Fill in lost thoughts, Transcribe the audio, Summarize & Visualize the text - All in one clip",
"author": "Mike Alicea",

View file

@ -1,6 +1,6 @@
{
"name": "obsidian-scribe-plugin",
"version": "1.0.9",
"version": "1.1.0",
"description": "An Obsidian plugin for recording voice notes, transcribing the audio, and summarizing the text - All in one",
"main": "build/main.js",
"scripts": {

View file

@ -11,11 +11,11 @@ import { handleCommands } from './commands/commands';
import { getDefaultPathSettings } from './util/pathUtils';
import { AudioRecord } from './audioRecord/audioRecord';
import {
addAudioSourceToFrontmatter,
appendTextToNote,
createNewNote,
renameFile,
saveAudioRecording,
setupFileFrontmatter,
} from './util/fileUtils';
import {
chunkAndTranscribeWithOpenAi,
@ -48,6 +48,7 @@ const DEFAULT_STATE: ScribeState = {
export interface ScribeOptions {
isAppendToActiveFile?: boolean;
isOnlyTranscribeActive?: boolean;
isSaveAudioFileActive?: boolean;
}
export default class ScribePlugin extends Plugin {
@ -140,6 +141,10 @@ export default class ScribePlugin extends Plugin {
audioRecordingBuffer: recordingBuffer,
scribeOptions: scribeOptions,
});
if (!scribeOptions.isSaveAudioFileActive) {
await this.app.vault.delete(recordingFile);
}
} catch (error) {
new Notice(`Scribe: Something went wrong ${error.toString()}`);
console.error('Scribe: Something went wrong', error);
@ -234,7 +239,11 @@ export default class ScribePlugin extends Plugin {
audioRecordingBuffer: ArrayBuffer;
scribeOptions?: ScribeOptions;
}) {
const { isAppendToActiveFile, isOnlyTranscribeActive } = scribeOptions;
const {
isAppendToActiveFile,
isOnlyTranscribeActive,
isSaveAudioFileActive,
} = scribeOptions;
const scribeNoteFilename = `${formatFilenamePrefix(
this.settings.noteFilenamePrefix,
this.settings.dateFilenameFormat,
@ -252,7 +261,11 @@ export default class ScribePlugin extends Plugin {
this.app.workspace.openLinkText(note?.path, currentPath, true);
}
await addAudioSourceToFrontmatter(this, note, audioRecordingFile);
if (isSaveAudioFileActive) {
await setupFileFrontmatter(this, note, audioRecordingFile);
} else {
await setupFileFrontmatter(this, note);
}
await this.cleanup();

View file

@ -7,26 +7,18 @@ export function ModalRecordingOptions({
options: ScribeOptions;
setOptions: React.Dispatch<ScribeOptions>;
}) {
const handleChangeIsAppendToActiveFile = (
event: React.ChangeEvent<HTMLInputElement>,
) => {
// setIsAppendToActiveFile(event.target.checked);
const handleOptionsChange = (updatedOptions: ScribeOptions) => {
setOptions({
...options,
isAppendToActiveFile: event.target.checked,
...updatedOptions,
});
};
const handleChangeIsOnlyTranscribeActive = (
event: React.ChangeEvent<HTMLInputElement>,
) => {
setOptions({
...options,
isOnlyTranscribeActive: event.target.checked,
});
// setIsOnlyTranscribeActive(event.target.checked);
};
const { isAppendToActiveFile, isOnlyTranscribeActive } = options;
const {
isAppendToActiveFile,
isOnlyTranscribeActive,
isSaveAudioFileActive,
} = options;
return (
<div className="scribe-recording-options">
@ -34,7 +26,11 @@ export function ModalRecordingOptions({
<input
type="checkbox"
checked={isAppendToActiveFile}
onChange={handleChangeIsAppendToActiveFile}
onChange={(event) => {
handleOptionsChange({
isAppendToActiveFile: event.target.checked,
});
}}
/>
Append to active file
</label>
@ -43,10 +39,26 @@ export function ModalRecordingOptions({
<input
type="checkbox"
checked={isOnlyTranscribeActive}
onChange={handleChangeIsOnlyTranscribeActive}
onChange={(event) => {
handleOptionsChange({
isOnlyTranscribeActive: event.target.checked,
});
}}
/>
Only transcribe recording
</label>
<label>
<input
type="checkbox"
checked={isSaveAudioFileActive}
onChange={(event) => {
handleOptionsChange({
isSaveAudioFileActive: event.target.checked,
});
}}
/>
Save audio file
</label>
</div>
);
}

View file

@ -56,11 +56,10 @@ const ScribeModal: React.FC<{ plugin: ScribePlugin }> = ({ plugin }) => {
>(null);
const [scribeOptions, setScribeOptions] = useState<ScribeOptions>({
isAppendToActiveFile: false,
isOnlyTranscribeActive: false,
isOnlyTranscribeActive: plugin.settings.isOnlyTranscribeActive,
isSaveAudioFileActive: plugin.settings.isSaveAudioFileActive,
});
const { isAppendToActiveFile, isOnlyTranscribeActive } = scribeOptions;
const hasOpenAiApiKey = Boolean(plugin.settings.openAiApiKey);
const handleStart = async () => {
@ -90,10 +89,7 @@ const ScribeModal: React.FC<{ plugin: ScribePlugin }> = ({ plugin }) => {
setIsScribing(true);
setRecordingStartTimeMs(null);
setRecordingState('inactive');
await plugin.scribe({
isAppendToActiveFile,
isOnlyTranscribeActive,
});
await plugin.scribe(scribeOptions);
setIsPaused(false);
setIsActive(false);
setIsScribing(false);

View file

@ -17,6 +17,8 @@ export interface ScribePluginSettings {
recordingFilenamePrefix: string;
noteFilenamePrefix: string;
dateFilenameFormat: string;
isSaveAudioFileActive: boolean;
isOnlyTranscribeActive: boolean;
}
export const DEFAULT_SETTINGS: ScribePluginSettings = {
@ -29,6 +31,8 @@ export const DEFAULT_SETTINGS: ScribePluginSettings = {
noteFilenamePrefix: 'scribe-{{date}}-',
recordingFilenamePrefix: 'scribe-recording-{{date}}-',
dateFilenameFormat: 'YYYY-MM-DD',
isSaveAudioFileActive: true,
isOnlyTranscribeActive: false,
};
export async function handleSettingsTab(plugin: ScribePlugin) {
@ -116,6 +120,33 @@ export class ScribeSettingsTab extends PluginSettingTab {
component.setValue(this.plugin.settings.transcriptDirectory);
});
containerEl.createEl('h2', { text: 'Default recording options' });
new Setting(containerEl)
.setName('Save audio file')
.setDesc(
`Save the audio file after Scribing it. If false, the audio file will be permanently deleted after transcription. This will not affect the Command for "Transcribe existing file"`,
)
.addToggle((toggle) => {
toggle.setValue(this.plugin.settings.isSaveAudioFileActive);
toggle.onChange(async (value) => {
this.plugin.settings.isSaveAudioFileActive = value;
await this.saveSettings();
});
});
new Setting(containerEl)
.setName('Only transcribe recording')
.setDesc(
'If true, we will only transcribe the recording and not generate anything additional like a summary, insights or a new filename.',
)
.addToggle((toggle) => {
toggle.setValue(this.plugin.settings.isOnlyTranscribeActive);
toggle.onChange(async (value) => {
this.plugin.settings.isOnlyTranscribeActive = value;
await this.saveSettings();
});
});
containerEl.createEl('h2', { text: 'AI model options' });
new Setting(containerEl)
.setName('LLM model for creating the summary')

View file

@ -86,17 +86,18 @@ export async function renameFile(
);
}
const TRANSCRIPT_IN_PROGRESS_HEADER = '# Transcription In Progress';
export async function addAudioSourceToFrontmatter(
export async function setupFileFrontmatter(
plugin: ScribePlugin,
noteFile: TFile,
audioFile: TFile,
audioFile?: TFile,
) {
try {
await plugin.app.fileManager.processFrontMatter(noteFile, (frontMatter) => {
const newFrontMatter = {
...frontMatter,
source: [...(frontMatter.source || []), `[[${audioFile.path}]]`],
source: audioFile
? [...(frontMatter.source || []), `[[${audioFile.path}]]`]
: frontMatter.source,
created_by: '[[Scribe]]',
};