feat(lightwrite): add Beat/Lyrics Editor app

- Add NestJS backend with project, beat, marker, lyrics, export modules
- Add SvelteKit web app with wavesurfer.js waveform visualization
- Add BPM detection using Web Audio API peak detection
- Add marker timeline for parts, hooks, bridges
- Add lyrics editor with timestamp sync
- Add export to LRC, SRT, JSON formats
- Add shared-storage support for lightwrite
- Fix mana-core-auth env loading (add dotenv before validation)
- Add lightwrite to setup-databases.sh
- Fix matrix-onboarding-bot type errors (displayName → fullName)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Till-JS 2026-02-16 11:13:08 +01:00
parent 7b2ae94474
commit 78c7383d54
81 changed files with 5244 additions and 34 deletions

View file

@ -0,0 +1 @@
export * from './types';

View file

@ -0,0 +1,34 @@
export interface Beat {
id: string;
projectId: string;
storagePath: string;
filename?: string | null;
duration?: number | null;
bpm?: number | null;
bpmConfidence?: number | null;
waveformData?: WaveformData | null;
createdAt: Date;
}
export interface WaveformData {
peaks: number[];
sampleRate: number;
duration: number;
}
export interface CreateBeatDto {
projectId: string;
filename: string;
}
export interface UpdateBeatDto {
bpm?: number;
bpmConfidence?: number;
duration?: number;
waveformData?: WaveformData;
}
export interface BeatUploadResponse {
beat: Beat;
uploadUrl: string;
}

View file

@ -0,0 +1,57 @@
export type ExportFormat = 'lrc' | 'srt' | 'json' | 'video';
export interface ExportOptions {
format: ExportFormat;
includeMarkers?: boolean;
videoOptions?: VideoExportOptions;
}
export interface VideoExportOptions {
width: number;
height: number;
fps: number;
backgroundColor: string;
textColor: string;
highlightColor: string;
fontFamily: string;
fontSize: number;
}
export interface LrcExportResult {
content: string;
filename: string;
}
export interface SrtExportResult {
content: string;
filename: string;
}
export interface JsonExportResult {
data: JsonExportData;
filename: string;
}
export interface JsonExportData {
project: {
id: string;
title: string;
description?: string;
};
beat: {
bpm?: number;
duration?: number;
};
markers: Array<{
type: string;
label?: string;
startTime: number;
endTime?: number;
}>;
lyrics: Array<{
lineNumber: number;
text: string;
startTime?: number;
endTime?: number;
}>;
}

View file

@ -0,0 +1,5 @@
export * from './project';
export * from './beat';
export * from './marker';
export * from './lyrics';
export * from './export';

View file

@ -0,0 +1,55 @@
export interface Lyrics {
id: string;
projectId: string;
content?: string | null;
}
export interface LyricLine {
id: string;
lyricsId: string;
lineNumber: number;
text: string;
startTime?: number | null;
endTime?: number | null;
}
export interface CreateLyricsDto {
projectId: string;
content?: string;
}
export interface UpdateLyricsDto {
content?: string;
}
export interface CreateLyricLineDto {
lyricsId: string;
lineNumber: number;
text: string;
startTime?: number;
endTime?: number;
}
export interface UpdateLyricLineDto {
text?: string;
startTime?: number;
endTime?: number;
}
export interface SyncedLyrics {
lines: SyncedLine[];
}
export interface SyncedLine {
lineNumber: number;
text: string;
startTime: number;
endTime?: number;
words?: SyncedWord[];
}
export interface SyncedWord {
word: string;
startTime: number;
endTime: number;
}

View file

@ -0,0 +1,49 @@
export type MarkerType =
| 'verse'
| 'hook'
| 'bridge'
| 'intro'
| 'outro'
| 'drop'
| 'breakdown'
| 'custom';
export interface Marker {
id: string;
beatId: string;
type: MarkerType;
label?: string | null;
startTime: number;
endTime?: number | null;
color?: string | null;
sortOrder?: number | null;
}
export interface CreateMarkerDto {
beatId: string;
type: MarkerType;
label?: string;
startTime: number;
endTime?: number;
color?: string;
}
export interface UpdateMarkerDto {
type?: MarkerType;
label?: string;
startTime?: number;
endTime?: number;
color?: string;
sortOrder?: number;
}
export const MARKER_COLORS: Record<MarkerType, string> = {
verse: '#3B82F6', // blue
hook: '#EF4444', // red
bridge: '#8B5CF6', // purple
intro: '#22C55E', // green
outro: '#F97316', // orange
drop: '#EC4899', // pink
breakdown: '#14B8A6', // teal
custom: '#6B7280', // gray
};

View file

@ -0,0 +1,18 @@
export interface Project {
id: string;
userId: string;
title: string;
description?: string | null;
createdAt: Date;
updatedAt: Date;
}
export interface CreateProjectDto {
title: string;
description?: string;
}
export interface UpdateProjectDto {
title?: string;
description?: string;
}