Initial commit: Tonemark PWA
Some checks failed
Build & Push Docker Image / build-and-push (push) Failing after 11s

Tonemark is a SvelteKit PWA for transcribing YouTube videos, audio
and video files, and microphone recordings using a local Whisper backend.

Features:
- Dark glassmorphic UI with electric-lime accent (5 switchable themes)
- Rail nav (desktop) / tab bar (mobile) layout
- Drop zone, YouTube URL input, and live audio recording inputs
- Audio mode waveform cards (none / standard / aggressive / auto)
- Real-time transcription progress with animated waveform
- Job queue with SSE streaming updates
- Push notifications on job completion
- PWA with native SvelteKit service worker
- SRT / TXT / MD / JSON transcript downloads

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Giancarmine Salucci
2026-05-06 16:41:25 +02:00
commit 13a96b6efa
68 changed files with 9712 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
import { json, error } from '@sveltejs/kit';
import { createJob, listJobs } from '$lib/server/db.js';
import { startYouTubeJob, startUploadJob } from '$lib/server/pipeline.js';
import type { AudioMode } from '$lib/types.js';
export async function GET() {
return json(listJobs());
}
export async function POST({ request }) {
const contentType = request.headers.get('content-type') ?? '';
let url: string | null = null;
let audioMode: AudioMode = 'auto';
let language: string | undefined;
let fileBuffer: Buffer | null = null;
let filename = 'upload';
if (contentType.includes('application/json')) {
const body = await request.json();
url = body.url ?? null;
audioMode = body.audioMode ?? 'auto';
language = body.language;
} else if (contentType.includes('multipart/form-data')) {
const form = await request.formData();
url = form.get('url')?.toString() ?? null;
audioMode = (form.get('audioMode')?.toString() as AudioMode) ?? 'auto';
language = form.get('language')?.toString();
const file = form.get('file');
if (file instanceof File) {
fileBuffer = Buffer.from(await file.arrayBuffer());
filename = file.name;
}
} else {
throw error(415, 'Unsupported content type');
}
if (!url && !fileBuffer) throw error(400, 'Provide url or file');
const jobId = url
? await startYouTubeJob(url, audioMode, language)
: await startUploadJob(fileBuffer!, filename, audioMode, language);
return json({ id: jobId }, { status: 201 });
}