Compare commits
7 Commits
sidecar-v1
...
sidecar-v1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73eab2e80c | ||
|
|
33ca3e4a28 | ||
|
|
e65d8b0510 | ||
|
|
a7364f2e50 | ||
|
|
809acfc781 | ||
|
|
96e9a6d38b | ||
|
|
ddfbd65478 |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "voice-to-notes",
|
"name": "voice-to-notes",
|
||||||
"version": "0.2.32",
|
"version": "0.2.35",
|
||||||
"description": "Desktop app for transcribing audio/video with speaker identification",
|
"description": "Desktop app for transcribing audio/video with speaker identification",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "voice-to-notes"
|
name = "voice-to-notes"
|
||||||
version = "1.0.12"
|
version = "1.0.13"
|
||||||
description = "Python sidecar for Voice to Notes — transcription, diarization, and AI services"
|
description = "Python sidecar for Voice to Notes — transcription, diarization, and AI services"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
@@ -113,17 +113,22 @@ class TranscribeService:
|
|||||||
compute_type: str = "int8",
|
compute_type: str = "int8",
|
||||||
language: str | None = None,
|
language: str | None = None,
|
||||||
on_segment: Callable[[SegmentResult, int], None] | None = None,
|
on_segment: Callable[[SegmentResult, int], None] | None = None,
|
||||||
|
chunk_label: str | None = None,
|
||||||
) -> TranscriptionResult:
|
) -> TranscriptionResult:
|
||||||
"""Transcribe an audio file with word-level timestamps.
|
"""Transcribe an audio file with word-level timestamps.
|
||||||
|
|
||||||
Sends progress messages via IPC during processing.
|
Sends progress messages via IPC during processing.
|
||||||
|
If chunk_label is set (e.g. "chunk 3/12"), messages are prefixed with it.
|
||||||
"""
|
"""
|
||||||
# Stage: loading model
|
prefix = f"{chunk_label}: " if chunk_label else ""
|
||||||
write_message(progress_message(request_id, 0, "loading_model", f"Loading {model_name}..."))
|
|
||||||
|
# Stage: loading model (skip for chunks after the first — model already loaded)
|
||||||
|
if not chunk_label:
|
||||||
|
write_message(progress_message(request_id, 0, "loading_model", f"Loading {model_name}..."))
|
||||||
model = self._ensure_model(model_name, device, compute_type)
|
model = self._ensure_model(model_name, device, compute_type)
|
||||||
|
|
||||||
# Stage: transcribing
|
# Stage: transcribing
|
||||||
write_message(progress_message(request_id, 10, "transcribing", "Starting transcription..."))
|
write_message(progress_message(request_id, 10, "transcribing", f"{prefix}Starting transcription..."))
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
segments_iter, info = model.transcribe(
|
segments_iter, info = model.transcribe(
|
||||||
@@ -176,7 +181,7 @@ class TranscribeService:
|
|||||||
request_id,
|
request_id,
|
||||||
progress_pct,
|
progress_pct,
|
||||||
"transcribing",
|
"transcribing",
|
||||||
f"Transcribing segment {segment_count} ({progress_pct}% of audio)...",
|
f"{prefix}Transcribing segment {segment_count} ({progress_pct}% of audio)...",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -271,6 +276,7 @@ class TranscribeService:
|
|||||||
chunk_result = self.transcribe(
|
chunk_result = self.transcribe(
|
||||||
request_id, tmp.name, model_name, device,
|
request_id, tmp.name, model_name, device,
|
||||||
compute_type, language, on_segment=chunk_on_segment,
|
compute_type, language, on_segment=chunk_on_segment,
|
||||||
|
chunk_label=f"Chunk {chunk_idx + 1}/{num_chunks}",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Offset timestamps and merge
|
# Offset timestamps and merge
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "voice-to-notes"
|
name = "voice-to-notes"
|
||||||
version = "0.2.32"
|
version = "0.2.35"
|
||||||
description = "Voice to Notes — desktop transcription with speaker identification"
|
description = "Voice to Notes — desktop transcription with speaker identification"
|
||||||
authors = ["Voice to Notes Contributors"]
|
authors = ["Voice to Notes Contributors"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Voice to Notes",
|
"productName": "Voice to Notes",
|
||||||
"version": "0.2.32",
|
"version": "0.2.35",
|
||||||
"identifier": "com.voicetonotes.app",
|
"identifier": "com.voicetonotes.app",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "npm run dev",
|
"beforeDevCommand": "npm run dev",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
import { segments, speakers } from '$lib/stores/transcript';
|
import { segments, speakers } from '$lib/stores/transcript';
|
||||||
import { settings } from '$lib/stores/settings';
|
import { settings, configureAIProvider } from '$lib/stores/settings';
|
||||||
|
|
||||||
interface ChatMessage {
|
interface ChatMessage {
|
||||||
role: 'user' | 'assistant';
|
role: 'user' | 'assistant';
|
||||||
@@ -45,22 +45,12 @@
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
// Ensure the provider is configured with current credentials before chatting
|
// Ensure the provider is configured with current credentials before chatting
|
||||||
const s = $settings;
|
await configureAIProvider($settings);
|
||||||
const configMap: Record<string, Record<string, string>> = {
|
|
||||||
openai: { api_key: s.openai_api_key, model: s.openai_model },
|
|
||||||
anthropic: { api_key: s.anthropic_api_key, model: s.anthropic_model },
|
|
||||||
litellm: { api_key: s.litellm_api_key, api_base: s.litellm_api_base, model: s.litellm_model },
|
|
||||||
local: { model: s.local_model_path, base_url: 'http://localhost:8080' },
|
|
||||||
};
|
|
||||||
const config = configMap[s.ai_provider];
|
|
||||||
if (config) {
|
|
||||||
await invoke('ai_configure', { provider: s.ai_provider, config });
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await invoke<{ response: string }>('ai_chat', {
|
const result = await invoke<{ response: string }>('ai_chat', {
|
||||||
messages: chatMessages,
|
messages: chatMessages,
|
||||||
transcriptContext: getTranscriptContext(),
|
transcriptContext: getTranscriptContext(),
|
||||||
provider: s.ai_provider,
|
provider: $settings.ai_provider,
|
||||||
});
|
});
|
||||||
|
|
||||||
messages = [...messages, { role: 'assistant', content: result.response }];
|
messages = [...messages, { role: 'assistant', content: result.response }];
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export async function configureAIProvider(s: AppSettings): Promise<void> {
|
|||||||
openai: { api_key: s.openai_api_key, model: s.openai_model },
|
openai: { api_key: s.openai_api_key, model: s.openai_model },
|
||||||
anthropic: { api_key: s.anthropic_api_key, model: s.anthropic_model },
|
anthropic: { api_key: s.anthropic_api_key, model: s.anthropic_model },
|
||||||
litellm: { api_key: s.litellm_api_key, api_base: s.litellm_api_base, model: s.litellm_model },
|
litellm: { api_key: s.litellm_api_key, api_base: s.litellm_api_base, model: s.litellm_model },
|
||||||
local: { model: s.ollama_model, base_url: s.ollama_url + '/v1' },
|
local: { model: s.ollama_model, base_url: s.ollama_url.replace(/\/+$/, '') + '/v1' },
|
||||||
};
|
};
|
||||||
const config = configMap[s.ai_provider];
|
const config = configMap[s.ai_provider];
|
||||||
if (config) {
|
if (config) {
|
||||||
|
|||||||
Reference in New Issue
Block a user