karaoke-gen 0.71.27__py3-none-any.whl → 0.75.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- karaoke_gen/__init__.py +32 -1
- karaoke_gen/audio_fetcher.py +476 -56
- karaoke_gen/audio_processor.py +11 -3
- karaoke_gen/file_handler.py +192 -0
- karaoke_gen/instrumental_review/__init__.py +45 -0
- karaoke_gen/instrumental_review/analyzer.py +408 -0
- karaoke_gen/instrumental_review/editor.py +322 -0
- karaoke_gen/instrumental_review/models.py +171 -0
- karaoke_gen/instrumental_review/server.py +475 -0
- karaoke_gen/instrumental_review/static/index.html +1506 -0
- karaoke_gen/instrumental_review/waveform.py +409 -0
- karaoke_gen/karaoke_finalise/karaoke_finalise.py +62 -1
- karaoke_gen/karaoke_gen.py +114 -1
- karaoke_gen/lyrics_processor.py +81 -4
- karaoke_gen/utils/bulk_cli.py +3 -0
- karaoke_gen/utils/cli_args.py +9 -2
- karaoke_gen/utils/gen_cli.py +379 -2
- karaoke_gen/utils/remote_cli.py +1126 -77
- {karaoke_gen-0.71.27.dist-info → karaoke_gen-0.75.16.dist-info}/METADATA +7 -1
- {karaoke_gen-0.71.27.dist-info → karaoke_gen-0.75.16.dist-info}/RECORD +38 -26
- lyrics_transcriber/correction/anchor_sequence.py +226 -350
- lyrics_transcriber/frontend/package.json +1 -1
- lyrics_transcriber/frontend/src/components/Header.tsx +38 -12
- lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +17 -3
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/SyncControls.tsx +185 -0
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/TimelineCanvas.tsx +704 -0
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/UpcomingWordsBar.tsx +80 -0
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/index.tsx +905 -0
- lyrics_transcriber/frontend/src/components/ModeSelectionModal.tsx +127 -0
- lyrics_transcriber/frontend/src/components/ReplaceAllLyricsModal.tsx +190 -542
- lyrics_transcriber/frontend/tsconfig.tsbuildinfo +1 -1
- lyrics_transcriber/frontend/web_assets/assets/{index-DdJTDWH3.js → index-COYImAcx.js} +1722 -489
- lyrics_transcriber/frontend/web_assets/assets/index-COYImAcx.js.map +1 -0
- lyrics_transcriber/frontend/web_assets/index.html +1 -1
- lyrics_transcriber/review/server.py +5 -5
- lyrics_transcriber/frontend/web_assets/assets/index-DdJTDWH3.js.map +0 -1
- {karaoke_gen-0.71.27.dist-info → karaoke_gen-0.75.16.dist-info}/WHEEL +0 -0
- {karaoke_gen-0.71.27.dist-info → karaoke_gen-0.75.16.dist-info}/entry_points.txt +0 -0
- {karaoke_gen-0.71.27.dist-info → karaoke_gen-0.75.16.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Box, Button, Typography, useMediaQuery, useTheme, Switch, FormControlLabel, Tooltip, Paper, IconButton } from '@mui/material'
|
|
1
|
+
import { Box, Button, Typography, useMediaQuery, useTheme, Switch, FormControlLabel, Tooltip, Paper, IconButton, Chip } from '@mui/material'
|
|
2
2
|
import LockIcon from '@mui/icons-material/Lock'
|
|
3
3
|
import UploadFileIcon from '@mui/icons-material/UploadFile'
|
|
4
4
|
import FindReplaceIcon from '@mui/icons-material/FindReplace'
|
|
@@ -7,6 +7,7 @@ import UndoIcon from '@mui/icons-material/Undo'
|
|
|
7
7
|
import RedoIcon from '@mui/icons-material/Redo'
|
|
8
8
|
import TimerIcon from '@mui/icons-material/Timer'
|
|
9
9
|
import RestoreIcon from '@mui/icons-material/Restore'
|
|
10
|
+
import RateReviewIcon from '@mui/icons-material/RateReview'
|
|
10
11
|
import { CorrectionData, InteractionMode } from '../types'
|
|
11
12
|
import CorrectionMetrics from './CorrectionMetrics'
|
|
12
13
|
import AgenticCorrectionMetrics from './AgenticCorrectionMetrics'
|
|
@@ -41,6 +42,8 @@ interface HeaderProps {
|
|
|
41
42
|
onRedo: () => void
|
|
42
43
|
canUndo: boolean
|
|
43
44
|
canRedo: boolean
|
|
45
|
+
annotationsEnabled?: boolean
|
|
46
|
+
onAnnotationsToggle?: (enabled: boolean) => void
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
export default function Header({
|
|
@@ -65,6 +68,8 @@ export default function Header({
|
|
|
65
68
|
onRedo,
|
|
66
69
|
canUndo,
|
|
67
70
|
canRedo,
|
|
71
|
+
annotationsEnabled = true,
|
|
72
|
+
onAnnotationsToggle,
|
|
68
73
|
}: HeaderProps) {
|
|
69
74
|
const theme = useTheme()
|
|
70
75
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'))
|
|
@@ -135,17 +140,38 @@ export default function Header({
|
|
|
135
140
|
<Typography variant="h4" sx={{ fontSize: isMobile ? '1.3rem' : '1.5rem' }}>
|
|
136
141
|
Nomad Karaoke: Lyrics Transcription Review
|
|
137
142
|
</Typography>
|
|
138
|
-
{
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
143
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
144
|
+
{!isReadOnly && onAnnotationsToggle && (
|
|
145
|
+
<Tooltip title={annotationsEnabled
|
|
146
|
+
? "Click to disable annotation prompts when editing"
|
|
147
|
+
: "Click to enable annotation prompts when editing"
|
|
148
|
+
}>
|
|
149
|
+
<Chip
|
|
150
|
+
icon={<RateReviewIcon />}
|
|
151
|
+
label={annotationsEnabled ? "Feedback On" : "Feedback Off"}
|
|
152
|
+
onClick={() => onAnnotationsToggle(!annotationsEnabled)}
|
|
153
|
+
color={annotationsEnabled ? "primary" : "default"}
|
|
154
|
+
variant={annotationsEnabled ? "filled" : "outlined"}
|
|
155
|
+
size="small"
|
|
156
|
+
sx={{
|
|
157
|
+
cursor: 'pointer',
|
|
158
|
+
'& .MuiChip-icon': { fontSize: '1rem' }
|
|
159
|
+
}}
|
|
160
|
+
/>
|
|
161
|
+
</Tooltip>
|
|
162
|
+
)}
|
|
163
|
+
{isReadOnly && (
|
|
164
|
+
<Button
|
|
165
|
+
variant="outlined"
|
|
166
|
+
size="small"
|
|
167
|
+
startIcon={<UploadFileIcon />}
|
|
168
|
+
onClick={onFileLoad}
|
|
169
|
+
fullWidth={isMobile}
|
|
170
|
+
>
|
|
171
|
+
Load File
|
|
172
|
+
</Button>
|
|
173
|
+
)}
|
|
174
|
+
</Box>
|
|
149
175
|
</Box>
|
|
150
176
|
|
|
151
177
|
<Box sx={{
|
|
@@ -200,6 +200,8 @@ interface MemoizedHeaderProps {
|
|
|
200
200
|
canUndo: boolean
|
|
201
201
|
canRedo: boolean
|
|
202
202
|
onUnCorrectAll: () => void
|
|
203
|
+
annotationsEnabled: boolean
|
|
204
|
+
onAnnotationsToggle: (enabled: boolean) => void
|
|
203
205
|
}
|
|
204
206
|
|
|
205
207
|
// Create a memoized Header component
|
|
@@ -224,7 +226,9 @@ const MemoizedHeader = memo(function MemoizedHeader({
|
|
|
224
226
|
onRedo,
|
|
225
227
|
canUndo,
|
|
226
228
|
canRedo,
|
|
227
|
-
onUnCorrectAll
|
|
229
|
+
onUnCorrectAll,
|
|
230
|
+
annotationsEnabled,
|
|
231
|
+
onAnnotationsToggle
|
|
228
232
|
}: MemoizedHeaderProps) {
|
|
229
233
|
return (
|
|
230
234
|
<Header
|
|
@@ -249,6 +253,8 @@ const MemoizedHeader = memo(function MemoizedHeader({
|
|
|
249
253
|
canUndo={canUndo}
|
|
250
254
|
canRedo={canRedo}
|
|
251
255
|
onUnCorrectAll={onUnCorrectAll}
|
|
256
|
+
annotationsEnabled={annotationsEnabled}
|
|
257
|
+
onAnnotationsToggle={onAnnotationsToggle}
|
|
252
258
|
/>
|
|
253
259
|
);
|
|
254
260
|
});
|
|
@@ -295,13 +301,18 @@ export default function LyricsAnalyzer({ data: initialData, onFileLoad, apiClien
|
|
|
295
301
|
wordIdsAffected: string[]
|
|
296
302
|
gapId?: string
|
|
297
303
|
} | null>(null)
|
|
298
|
-
const [annotationsEnabled] = useState(() => {
|
|
304
|
+
const [annotationsEnabled, setAnnotationsEnabled] = useState(() => {
|
|
299
305
|
// Check localStorage for user preference
|
|
300
306
|
const saved = localStorage.getItem('annotationsEnabled')
|
|
301
307
|
return saved !== null ? saved === 'true' : true // Default: enabled
|
|
302
|
-
// TODO: Add UI toggle to enable/disable via setAnnotationsEnabled
|
|
303
308
|
})
|
|
304
309
|
|
|
310
|
+
// Persist annotation preference to localStorage
|
|
311
|
+
const handleAnnotationsToggle = useCallback((enabled: boolean) => {
|
|
312
|
+
setAnnotationsEnabled(enabled)
|
|
313
|
+
localStorage.setItem('annotationsEnabled', String(enabled))
|
|
314
|
+
}, [])
|
|
315
|
+
|
|
305
316
|
// Correction detail card state
|
|
306
317
|
const [correctionDetailOpen, setCorrectionDetailOpen] = useState(false)
|
|
307
318
|
const [selectedCorrection, setSelectedCorrection] = useState<{
|
|
@@ -1164,6 +1175,8 @@ export default function LyricsAnalyzer({ data: initialData, onFileLoad, apiClien
|
|
|
1164
1175
|
canUndo={canUndo}
|
|
1165
1176
|
canRedo={canRedo}
|
|
1166
1177
|
onUnCorrectAll={handleUnCorrectAll}
|
|
1178
|
+
annotationsEnabled={annotationsEnabled}
|
|
1179
|
+
onAnnotationsToggle={handleAnnotationsToggle}
|
|
1167
1180
|
/>
|
|
1168
1181
|
|
|
1169
1182
|
<Grid container direction={isMobile ? 'column' : 'row'}>
|
|
@@ -1313,6 +1326,7 @@ export default function LyricsAnalyzer({ data: initialData, onFileLoad, apiClien
|
|
|
1313
1326
|
onPlaySegment={handlePlaySegment}
|
|
1314
1327
|
currentTime={currentAudioTime}
|
|
1315
1328
|
setModalSpacebarHandler={handleSetModalSpacebarHandler}
|
|
1329
|
+
existingSegments={data.corrected_segments}
|
|
1316
1330
|
/>
|
|
1317
1331
|
|
|
1318
1332
|
{pendingAnnotation && (
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { memo } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Box,
|
|
4
|
+
Button,
|
|
5
|
+
Divider,
|
|
6
|
+
Stack
|
|
7
|
+
} from '@mui/material'
|
|
8
|
+
import PlayCircleOutlineIcon from '@mui/icons-material/PlayCircleOutline'
|
|
9
|
+
import StopIcon from '@mui/icons-material/Stop'
|
|
10
|
+
import PauseIcon from '@mui/icons-material/Pause'
|
|
11
|
+
import PlayArrowIcon from '@mui/icons-material/PlayArrow'
|
|
12
|
+
import ClearAllIcon from '@mui/icons-material/ClearAll'
|
|
13
|
+
import EditNoteIcon from '@mui/icons-material/EditNote'
|
|
14
|
+
import BlockIcon from '@mui/icons-material/Block'
|
|
15
|
+
import EditIcon from '@mui/icons-material/Edit'
|
|
16
|
+
import DeleteIcon from '@mui/icons-material/Delete'
|
|
17
|
+
|
|
18
|
+
interface SyncControlsProps {
|
|
19
|
+
// Main buttons
|
|
20
|
+
isManualSyncing: boolean
|
|
21
|
+
isPaused: boolean
|
|
22
|
+
onStartSync: () => void
|
|
23
|
+
onPauseSync: () => void
|
|
24
|
+
onResumeSync: () => void
|
|
25
|
+
onClearSync: () => void
|
|
26
|
+
onEditLyrics: () => void
|
|
27
|
+
|
|
28
|
+
// Playback controls
|
|
29
|
+
onPlay: () => void
|
|
30
|
+
onStop: () => void
|
|
31
|
+
isPlaying: boolean
|
|
32
|
+
|
|
33
|
+
// Word action buttons
|
|
34
|
+
hasSelectedWords: boolean
|
|
35
|
+
selectedWordCount: number
|
|
36
|
+
onUnsyncFromCursor: () => void
|
|
37
|
+
onEditSelectedWord: () => void
|
|
38
|
+
onDeleteSelected: () => void
|
|
39
|
+
|
|
40
|
+
// Additional state
|
|
41
|
+
canUnsyncFromCursor: boolean
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const SyncControls = memo(function SyncControls({
|
|
45
|
+
isManualSyncing,
|
|
46
|
+
isPaused,
|
|
47
|
+
onStartSync,
|
|
48
|
+
onPauseSync,
|
|
49
|
+
onResumeSync,
|
|
50
|
+
onClearSync,
|
|
51
|
+
onEditLyrics,
|
|
52
|
+
onPlay,
|
|
53
|
+
onStop,
|
|
54
|
+
isPlaying,
|
|
55
|
+
hasSelectedWords,
|
|
56
|
+
selectedWordCount,
|
|
57
|
+
onUnsyncFromCursor,
|
|
58
|
+
onEditSelectedWord,
|
|
59
|
+
onDeleteSelected,
|
|
60
|
+
canUnsyncFromCursor
|
|
61
|
+
}: SyncControlsProps) {
|
|
62
|
+
return (
|
|
63
|
+
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>
|
|
64
|
+
{/* Row 1: Playback & Sync Mode Controls */}
|
|
65
|
+
<Stack direction="row" spacing={1} alignItems="center" flexWrap="wrap">
|
|
66
|
+
{/* Playback controls */}
|
|
67
|
+
<Button
|
|
68
|
+
variant="outlined"
|
|
69
|
+
color="primary"
|
|
70
|
+
onClick={onPlay}
|
|
71
|
+
startIcon={<PlayArrowIcon />}
|
|
72
|
+
size="small"
|
|
73
|
+
disabled={isPlaying}
|
|
74
|
+
>
|
|
75
|
+
Play
|
|
76
|
+
</Button>
|
|
77
|
+
<Button
|
|
78
|
+
variant="outlined"
|
|
79
|
+
color="error"
|
|
80
|
+
onClick={onStop}
|
|
81
|
+
startIcon={<StopIcon />}
|
|
82
|
+
size="small"
|
|
83
|
+
disabled={!isPlaying}
|
|
84
|
+
>
|
|
85
|
+
Stop
|
|
86
|
+
</Button>
|
|
87
|
+
|
|
88
|
+
<Divider orientation="vertical" flexItem sx={{ mx: 0.5 }} />
|
|
89
|
+
|
|
90
|
+
{/* Sync Mode controls */}
|
|
91
|
+
{isManualSyncing ? (
|
|
92
|
+
<>
|
|
93
|
+
<Button
|
|
94
|
+
variant="contained"
|
|
95
|
+
color="error"
|
|
96
|
+
onClick={onStartSync}
|
|
97
|
+
startIcon={<StopIcon />}
|
|
98
|
+
size="small"
|
|
99
|
+
>
|
|
100
|
+
Stop Sync
|
|
101
|
+
</Button>
|
|
102
|
+
<Button
|
|
103
|
+
variant="outlined"
|
|
104
|
+
color={isPaused ? 'success' : 'warning'}
|
|
105
|
+
onClick={isPaused ? onResumeSync : onPauseSync}
|
|
106
|
+
startIcon={isPaused ? <PlayArrowIcon /> : <PauseIcon />}
|
|
107
|
+
size="small"
|
|
108
|
+
>
|
|
109
|
+
{isPaused ? 'Resume' : 'Pause'}
|
|
110
|
+
</Button>
|
|
111
|
+
</>
|
|
112
|
+
) : (
|
|
113
|
+
<Button
|
|
114
|
+
variant="contained"
|
|
115
|
+
color="primary"
|
|
116
|
+
onClick={onStartSync}
|
|
117
|
+
startIcon={<PlayCircleOutlineIcon />}
|
|
118
|
+
size="small"
|
|
119
|
+
>
|
|
120
|
+
Start Sync
|
|
121
|
+
</Button>
|
|
122
|
+
)}
|
|
123
|
+
</Stack>
|
|
124
|
+
|
|
125
|
+
{/* Row 2: Editing & Word Actions */}
|
|
126
|
+
<Stack direction="row" spacing={1} alignItems="center" flexWrap="wrap">
|
|
127
|
+
<Button
|
|
128
|
+
variant="outlined"
|
|
129
|
+
color="warning"
|
|
130
|
+
onClick={onClearSync}
|
|
131
|
+
startIcon={<ClearAllIcon />}
|
|
132
|
+
size="small"
|
|
133
|
+
disabled={isManualSyncing && !isPaused}
|
|
134
|
+
>
|
|
135
|
+
Clear Sync
|
|
136
|
+
</Button>
|
|
137
|
+
|
|
138
|
+
<Button
|
|
139
|
+
variant="outlined"
|
|
140
|
+
onClick={onEditLyrics}
|
|
141
|
+
startIcon={<EditNoteIcon />}
|
|
142
|
+
size="small"
|
|
143
|
+
disabled={isManualSyncing && !isPaused}
|
|
144
|
+
>
|
|
145
|
+
Edit Lyrics
|
|
146
|
+
</Button>
|
|
147
|
+
|
|
148
|
+
<Divider orientation="vertical" flexItem sx={{ mx: 0.5 }} />
|
|
149
|
+
|
|
150
|
+
<Button
|
|
151
|
+
variant="outlined"
|
|
152
|
+
onClick={onUnsyncFromCursor}
|
|
153
|
+
startIcon={<BlockIcon />}
|
|
154
|
+
size="small"
|
|
155
|
+
disabled={!canUnsyncFromCursor || (isManualSyncing && !isPaused)}
|
|
156
|
+
>
|
|
157
|
+
Unsync from Cursor
|
|
158
|
+
</Button>
|
|
159
|
+
|
|
160
|
+
<Button
|
|
161
|
+
variant="outlined"
|
|
162
|
+
onClick={onEditSelectedWord}
|
|
163
|
+
startIcon={<EditIcon />}
|
|
164
|
+
size="small"
|
|
165
|
+
disabled={!hasSelectedWords || selectedWordCount !== 1}
|
|
166
|
+
>
|
|
167
|
+
Edit Word
|
|
168
|
+
</Button>
|
|
169
|
+
|
|
170
|
+
<Button
|
|
171
|
+
variant="outlined"
|
|
172
|
+
color="error"
|
|
173
|
+
onClick={onDeleteSelected}
|
|
174
|
+
startIcon={<DeleteIcon />}
|
|
175
|
+
size="small"
|
|
176
|
+
disabled={!hasSelectedWords || (isManualSyncing && !isPaused)}
|
|
177
|
+
>
|
|
178
|
+
Delete{hasSelectedWords && selectedWordCount > 0 ? ` (${selectedWordCount})` : ''}
|
|
179
|
+
</Button>
|
|
180
|
+
</Stack>
|
|
181
|
+
</Box>
|
|
182
|
+
)
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
export default SyncControls
|