mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-18 02:09:39 +02:00
✨ 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:
parent
7b2ae94474
commit
78c7383d54
81 changed files with 5244 additions and 34 deletions
1
apps/lightwrite/packages/shared/src/index.ts
Normal file
1
apps/lightwrite/packages/shared/src/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './types';
|
||||
34
apps/lightwrite/packages/shared/src/types/beat.ts
Normal file
34
apps/lightwrite/packages/shared/src/types/beat.ts
Normal 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;
|
||||
}
|
||||
57
apps/lightwrite/packages/shared/src/types/export.ts
Normal file
57
apps/lightwrite/packages/shared/src/types/export.ts
Normal 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;
|
||||
}>;
|
||||
}
|
||||
5
apps/lightwrite/packages/shared/src/types/index.ts
Normal file
5
apps/lightwrite/packages/shared/src/types/index.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export * from './project';
|
||||
export * from './beat';
|
||||
export * from './marker';
|
||||
export * from './lyrics';
|
||||
export * from './export';
|
||||
55
apps/lightwrite/packages/shared/src/types/lyrics.ts
Normal file
55
apps/lightwrite/packages/shared/src/types/lyrics.ts
Normal 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;
|
||||
}
|
||||
49
apps/lightwrite/packages/shared/src/types/marker.ts
Normal file
49
apps/lightwrite/packages/shared/src/types/marker.ts
Normal 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
|
||||
};
|
||||
18
apps/lightwrite/packages/shared/src/types/project.ts
Normal file
18
apps/lightwrite/packages/shared/src/types/project.ts
Normal 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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue