lyrics-transcriber 0.49.3__py3-none-any.whl → 0.52.0__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.
- lyrics_transcriber/cli/cli_main.py +5 -1
- lyrics_transcriber/frontend/dist/assets/{index-DSQidWB1.js → index-C5ftSgQo.js} +633 -60
- lyrics_transcriber/frontend/dist/assets/index-C5ftSgQo.js.map +1 -0
- lyrics_transcriber/frontend/dist/index.html +1 -1
- lyrics_transcriber/frontend/src/components/Header.tsx +31 -0
- lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +125 -18
- lyrics_transcriber/frontend/src/components/PreviewVideoSection.tsx +26 -3
- lyrics_transcriber/frontend/src/components/ReviewChangesModal.tsx +16 -1
- lyrics_transcriber/frontend/src/components/TimingOffsetModal.tsx +131 -0
- lyrics_transcriber/frontend/src/components/shared/utils/keyboardHandlers.ts +8 -0
- lyrics_transcriber/frontend/src/components/shared/utils/timingUtils.ts +110 -0
- lyrics_transcriber/frontend/tsconfig.tsbuildinfo +1 -1
- lyrics_transcriber/output/cdg.py +10 -0
- lyrics_transcriber/transcribers/audioshake.py +1 -1
- {lyrics_transcriber-0.49.3.dist-info → lyrics_transcriber-0.52.0.dist-info}/LICENSE +1 -1
- {lyrics_transcriber-0.49.3.dist-info → lyrics_transcriber-0.52.0.dist-info}/METADATA +10 -9
- {lyrics_transcriber-0.49.3.dist-info → lyrics_transcriber-0.52.0.dist-info}/RECORD +19 -17
- {lyrics_transcriber-0.49.3.dist-info → lyrics_transcriber-0.52.0.dist-info}/WHEEL +1 -1
- lyrics_transcriber/frontend/dist/assets/index-DSQidWB1.js.map +0 -1
- {lyrics_transcriber-0.49.3.dist-info → lyrics_transcriber-0.52.0.dist-info}/entry_points.txt +0 -0
@@ -13646,7 +13646,7 @@ function getSvgIconUtilityClass(slot) {
|
|
13646
13646
|
return generateUtilityClass("MuiSvgIcon", slot);
|
13647
13647
|
}
|
13648
13648
|
generateUtilityClasses("MuiSvgIcon", ["root", "colorPrimary", "colorSecondary", "colorAction", "colorError", "colorDisabled", "fontSizeInherit", "fontSizeSmall", "fontSizeMedium", "fontSizeLarge"]);
|
13649
|
-
const useUtilityClasses$
|
13649
|
+
const useUtilityClasses$I = (ownerState) => {
|
13650
13650
|
const {
|
13651
13651
|
color: color2,
|
13652
13652
|
fontSize,
|
@@ -13791,7 +13791,7 @@ const SvgIcon = /* @__PURE__ */ reactExports.forwardRef(function SvgIcon2(inProp
|
|
13791
13791
|
if (!inheritViewBox) {
|
13792
13792
|
more.viewBox = viewBox;
|
13793
13793
|
}
|
13794
|
-
const classes = useUtilityClasses$
|
13794
|
+
const classes = useUtilityClasses$I(ownerState);
|
13795
13795
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(SvgIconRoot, {
|
13796
13796
|
as: component,
|
13797
13797
|
className: clsx(classes.root, className),
|
@@ -14298,7 +14298,7 @@ function getPaperUtilityClass(slot) {
|
|
14298
14298
|
return generateUtilityClass("MuiPaper", slot);
|
14299
14299
|
}
|
14300
14300
|
generateUtilityClasses("MuiPaper", ["root", "rounded", "outlined", "elevation", "elevation0", "elevation1", "elevation2", "elevation3", "elevation4", "elevation5", "elevation6", "elevation7", "elevation8", "elevation9", "elevation10", "elevation11", "elevation12", "elevation13", "elevation14", "elevation15", "elevation16", "elevation17", "elevation18", "elevation19", "elevation20", "elevation21", "elevation22", "elevation23", "elevation24"]);
|
14301
|
-
const useUtilityClasses$
|
14301
|
+
const useUtilityClasses$H = (ownerState) => {
|
14302
14302
|
const {
|
14303
14303
|
square,
|
14304
14304
|
elevation,
|
@@ -14371,7 +14371,7 @@ const Paper = /* @__PURE__ */ reactExports.forwardRef(function Paper2(inProps, r
|
|
14371
14371
|
square,
|
14372
14372
|
variant
|
14373
14373
|
};
|
14374
|
-
const classes = useUtilityClasses$
|
14374
|
+
const classes = useUtilityClasses$H(ownerState);
|
14375
14375
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(PaperRoot, {
|
14376
14376
|
as: component,
|
14377
14377
|
ownerState,
|
@@ -14832,7 +14832,7 @@ function getButtonBaseUtilityClass(slot) {
|
|
14832
14832
|
return generateUtilityClass("MuiButtonBase", slot);
|
14833
14833
|
}
|
14834
14834
|
const buttonBaseClasses = generateUtilityClasses("MuiButtonBase", ["root", "disabled", "focusVisible"]);
|
14835
|
-
const useUtilityClasses$
|
14835
|
+
const useUtilityClasses$G = (ownerState) => {
|
14836
14836
|
const {
|
14837
14837
|
disabled,
|
14838
14838
|
focusVisible,
|
@@ -15049,7 +15049,7 @@ const ButtonBase = /* @__PURE__ */ reactExports.forwardRef(function ButtonBase2(
|
|
15049
15049
|
tabIndex,
|
15050
15050
|
focusVisible
|
15051
15051
|
};
|
15052
|
-
const classes = useUtilityClasses$
|
15052
|
+
const classes = useUtilityClasses$G(ownerState);
|
15053
15053
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(ButtonBaseRoot, {
|
15054
15054
|
as: ComponentProp,
|
15055
15055
|
className: clsx(classes.root, className),
|
@@ -15147,7 +15147,7 @@ const rotateAnimation = typeof circularRotateKeyframe !== "string" ? css`
|
|
15147
15147
|
const dashAnimation = typeof circularDashKeyframe !== "string" ? css`
|
15148
15148
|
animation: ${circularDashKeyframe} 1.4s ease-in-out infinite;
|
15149
15149
|
` : null;
|
15150
|
-
const useUtilityClasses$
|
15150
|
+
const useUtilityClasses$F = (ownerState) => {
|
15151
15151
|
const {
|
15152
15152
|
classes,
|
15153
15153
|
variant,
|
@@ -15270,7 +15270,7 @@ const CircularProgress = /* @__PURE__ */ reactExports.forwardRef(function Circul
|
|
15270
15270
|
value,
|
15271
15271
|
variant
|
15272
15272
|
};
|
15273
|
-
const classes = useUtilityClasses$
|
15273
|
+
const classes = useUtilityClasses$F(ownerState);
|
15274
15274
|
const circleStyle = {};
|
15275
15275
|
const rootStyle = {};
|
15276
15276
|
const rootProps = {};
|
@@ -15315,7 +15315,7 @@ function getIconButtonUtilityClass(slot) {
|
|
15315
15315
|
return generateUtilityClass("MuiIconButton", slot);
|
15316
15316
|
}
|
15317
15317
|
const iconButtonClasses = generateUtilityClasses("MuiIconButton", ["root", "disabled", "colorInherit", "colorPrimary", "colorSecondary", "colorError", "colorInfo", "colorSuccess", "colorWarning", "edgeStart", "edgeEnd", "sizeSmall", "sizeMedium", "sizeLarge", "loading", "loadingIndicator", "loadingWrapper"]);
|
15318
|
-
const useUtilityClasses$
|
15318
|
+
const useUtilityClasses$E = (ownerState) => {
|
15319
15319
|
const {
|
15320
15320
|
classes,
|
15321
15321
|
disabled,
|
@@ -15501,7 +15501,7 @@ const IconButton = /* @__PURE__ */ reactExports.forwardRef(function IconButton2(
|
|
15501
15501
|
loadingIndicator,
|
15502
15502
|
size
|
15503
15503
|
};
|
15504
|
-
const classes = useUtilityClasses$
|
15504
|
+
const classes = useUtilityClasses$E(ownerState);
|
15505
15505
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(IconButtonRoot, {
|
15506
15506
|
id,
|
15507
15507
|
className: clsx(classes.root, className),
|
@@ -15540,7 +15540,7 @@ const InfoOutlinedIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("pa
|
|
15540
15540
|
const ClearIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
15541
15541
|
d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"
|
15542
15542
|
}), "Close");
|
15543
|
-
const useUtilityClasses$
|
15543
|
+
const useUtilityClasses$D = (ownerState) => {
|
15544
15544
|
const {
|
15545
15545
|
variant,
|
15546
15546
|
color: color2,
|
@@ -15695,7 +15695,7 @@ const Alert = /* @__PURE__ */ reactExports.forwardRef(function Alert2(inProps, r
|
|
15695
15695
|
variant,
|
15696
15696
|
colorSeverity: color2 || severity
|
15697
15697
|
};
|
15698
|
-
const classes = useUtilityClasses$
|
15698
|
+
const classes = useUtilityClasses$D(ownerState);
|
15699
15699
|
const externalForwardedProps = {
|
15700
15700
|
slots: {
|
15701
15701
|
closeButton: components.CloseButton,
|
@@ -15794,7 +15794,7 @@ const v6Colors = {
|
|
15794
15794
|
textDisabled: true
|
15795
15795
|
};
|
15796
15796
|
const extendSxProp = internal_createExtendSxProp();
|
15797
|
-
const useUtilityClasses$
|
15797
|
+
const useUtilityClasses$C = (ownerState) => {
|
15798
15798
|
const {
|
15799
15799
|
align,
|
15800
15800
|
gutterBottom,
|
@@ -15937,7 +15937,7 @@ const Typography = /* @__PURE__ */ reactExports.forwardRef(function Typography2(
|
|
15937
15937
|
variantMapping
|
15938
15938
|
};
|
15939
15939
|
const Component = component || (paragraph ? "p" : variantMapping[variant] || defaultVariantMapping[variant]) || "span";
|
15940
|
-
const classes = useUtilityClasses$
|
15940
|
+
const classes = useUtilityClasses$C(ownerState);
|
15941
15941
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(TypographyRoot, {
|
15942
15942
|
as: Component,
|
15943
15943
|
ref,
|
@@ -17361,7 +17361,7 @@ function resolveAnchorEl$1(anchorEl) {
|
|
17361
17361
|
function isHTMLElement(element) {
|
17362
17362
|
return element.nodeType !== void 0;
|
17363
17363
|
}
|
17364
|
-
const useUtilityClasses$
|
17364
|
+
const useUtilityClasses$B = (ownerState) => {
|
17365
17365
|
const {
|
17366
17366
|
classes
|
17367
17367
|
} = ownerState;
|
@@ -17462,7 +17462,7 @@ const PopperTooltip = /* @__PURE__ */ reactExports.forwardRef(function PopperToo
|
|
17462
17462
|
if (TransitionProps !== null) {
|
17463
17463
|
childProps.TransitionProps = TransitionProps;
|
17464
17464
|
}
|
17465
|
-
const classes = useUtilityClasses$
|
17465
|
+
const classes = useUtilityClasses$B(props);
|
17466
17466
|
const Root = slots.root ?? "div";
|
17467
17467
|
const rootProps = useSlotProps({
|
17468
17468
|
elementType: Root,
|
@@ -17814,7 +17814,7 @@ const inputOverridesResolver = (props, styles2) => {
|
|
17814
17814
|
} = props;
|
17815
17815
|
return [styles2.input, ownerState.size === "small" && styles2.inputSizeSmall, ownerState.multiline && styles2.inputMultiline, ownerState.type === "search" && styles2.inputTypeSearch, ownerState.startAdornment && styles2.inputAdornedStart, ownerState.endAdornment && styles2.inputAdornedEnd, ownerState.hiddenLabel && styles2.inputHiddenLabel];
|
17816
17816
|
};
|
17817
|
-
const useUtilityClasses$
|
17817
|
+
const useUtilityClasses$A = (ownerState) => {
|
17818
17818
|
const {
|
17819
17819
|
classes,
|
17820
17820
|
color: color2,
|
@@ -18200,7 +18200,7 @@ const InputBase = /* @__PURE__ */ reactExports.forwardRef(function InputBase2(in
|
|
18200
18200
|
startAdornment,
|
18201
18201
|
type
|
18202
18202
|
};
|
18203
|
-
const classes = useUtilityClasses$
|
18203
|
+
const classes = useUtilityClasses$A(ownerState);
|
18204
18204
|
const Root = slots.root || components.Root || InputBaseRoot;
|
18205
18205
|
const rootProps = slotProps.root || componentsProps.root || {};
|
18206
18206
|
const Input3 = slots.input || components.Input || InputBaseInput;
|
@@ -18405,7 +18405,7 @@ function getBackdropUtilityClass(slot) {
|
|
18405
18405
|
return generateUtilityClass("MuiBackdrop", slot);
|
18406
18406
|
}
|
18407
18407
|
generateUtilityClasses("MuiBackdrop", ["root", "invisible"]);
|
18408
|
-
const useUtilityClasses$
|
18408
|
+
const useUtilityClasses$z = (ownerState) => {
|
18409
18409
|
const {
|
18410
18410
|
classes,
|
18411
18411
|
invisible
|
@@ -18468,7 +18468,7 @@ const Backdrop = /* @__PURE__ */ reactExports.forwardRef(function Backdrop2(inPr
|
|
18468
18468
|
component,
|
18469
18469
|
invisible
|
18470
18470
|
};
|
18471
|
-
const classes = useUtilityClasses$
|
18471
|
+
const classes = useUtilityClasses$z(ownerState);
|
18472
18472
|
const backwardCompatibleSlots = {
|
18473
18473
|
transition: TransitionComponentProp,
|
18474
18474
|
root: components.Root,
|
@@ -18521,7 +18521,7 @@ function getButtonUtilityClass(slot) {
|
|
18521
18521
|
const buttonClasses = generateUtilityClasses("MuiButton", ["root", "text", "textInherit", "textPrimary", "textSecondary", "textSuccess", "textError", "textInfo", "textWarning", "outlined", "outlinedInherit", "outlinedPrimary", "outlinedSecondary", "outlinedSuccess", "outlinedError", "outlinedInfo", "outlinedWarning", "contained", "containedInherit", "containedPrimary", "containedSecondary", "containedSuccess", "containedError", "containedInfo", "containedWarning", "disableElevation", "focusVisible", "disabled", "colorInherit", "colorPrimary", "colorSecondary", "colorSuccess", "colorError", "colorInfo", "colorWarning", "textSizeSmall", "textSizeMedium", "textSizeLarge", "outlinedSizeSmall", "outlinedSizeMedium", "outlinedSizeLarge", "containedSizeSmall", "containedSizeMedium", "containedSizeLarge", "sizeMedium", "sizeSmall", "sizeLarge", "fullWidth", "startIcon", "endIcon", "icon", "iconSizeSmall", "iconSizeMedium", "iconSizeLarge", "loading", "loadingWrapper", "loadingIconPlaceholder", "loadingIndicator", "loadingPositionCenter", "loadingPositionStart", "loadingPositionEnd"]);
|
18522
18522
|
const ButtonGroupContext = /* @__PURE__ */ reactExports.createContext({});
|
18523
18523
|
const ButtonGroupButtonContext = /* @__PURE__ */ reactExports.createContext(void 0);
|
18524
|
-
const useUtilityClasses$
|
18524
|
+
const useUtilityClasses$y = (ownerState) => {
|
18525
18525
|
const {
|
18526
18526
|
color: color2,
|
18527
18527
|
disableElevation,
|
@@ -19023,7 +19023,7 @@ const Button = /* @__PURE__ */ reactExports.forwardRef(function Button2(inProps,
|
|
19023
19023
|
type,
|
19024
19024
|
variant
|
19025
19025
|
};
|
19026
|
-
const classes = useUtilityClasses$
|
19026
|
+
const classes = useUtilityClasses$y(ownerState);
|
19027
19027
|
const startIcon = (startIconProp || loading && loadingPosition === "start") && /* @__PURE__ */ jsxRuntimeExports.jsx(ButtonStartIcon, {
|
19028
19028
|
className: classes.startIcon,
|
19029
19029
|
ownerState,
|
@@ -19070,6 +19070,307 @@ const Button = /* @__PURE__ */ reactExports.forwardRef(function Button2(inProps,
|
|
19070
19070
|
children: [startIcon, loadingPosition !== "end" && loader, children, loadingPosition === "end" && loader, endIcon]
|
19071
19071
|
});
|
19072
19072
|
});
|
19073
|
+
function getButtonGroupUtilityClass(slot) {
|
19074
|
+
return generateUtilityClass("MuiButtonGroup", slot);
|
19075
|
+
}
|
19076
|
+
const buttonGroupClasses = generateUtilityClasses("MuiButtonGroup", ["root", "contained", "outlined", "text", "disableElevation", "disabled", "firstButton", "fullWidth", "horizontal", "vertical", "colorPrimary", "colorSecondary", "grouped", "groupedHorizontal", "groupedVertical", "groupedText", "groupedTextHorizontal", "groupedTextVertical", "groupedTextPrimary", "groupedTextSecondary", "groupedOutlined", "groupedOutlinedHorizontal", "groupedOutlinedVertical", "groupedOutlinedPrimary", "groupedOutlinedSecondary", "groupedContained", "groupedContainedHorizontal", "groupedContainedVertical", "groupedContainedPrimary", "groupedContainedSecondary", "lastButton", "middleButton"]);
|
19077
|
+
const overridesResolver$2 = (props, styles2) => {
|
19078
|
+
const {
|
19079
|
+
ownerState
|
19080
|
+
} = props;
|
19081
|
+
return [{
|
19082
|
+
[`& .${buttonGroupClasses.grouped}`]: styles2.grouped
|
19083
|
+
}, {
|
19084
|
+
[`& .${buttonGroupClasses.grouped}`]: styles2[`grouped${capitalize(ownerState.orientation)}`]
|
19085
|
+
}, {
|
19086
|
+
[`& .${buttonGroupClasses.grouped}`]: styles2[`grouped${capitalize(ownerState.variant)}`]
|
19087
|
+
}, {
|
19088
|
+
[`& .${buttonGroupClasses.grouped}`]: styles2[`grouped${capitalize(ownerState.variant)}${capitalize(ownerState.orientation)}`]
|
19089
|
+
}, {
|
19090
|
+
[`& .${buttonGroupClasses.grouped}`]: styles2[`grouped${capitalize(ownerState.variant)}${capitalize(ownerState.color)}`]
|
19091
|
+
}, {
|
19092
|
+
[`& .${buttonGroupClasses.firstButton}`]: styles2.firstButton
|
19093
|
+
}, {
|
19094
|
+
[`& .${buttonGroupClasses.lastButton}`]: styles2.lastButton
|
19095
|
+
}, {
|
19096
|
+
[`& .${buttonGroupClasses.middleButton}`]: styles2.middleButton
|
19097
|
+
}, styles2.root, styles2[ownerState.variant], ownerState.disableElevation === true && styles2.disableElevation, ownerState.fullWidth && styles2.fullWidth, ownerState.orientation === "vertical" && styles2.vertical];
|
19098
|
+
};
|
19099
|
+
const useUtilityClasses$x = (ownerState) => {
|
19100
|
+
const {
|
19101
|
+
classes,
|
19102
|
+
color: color2,
|
19103
|
+
disabled,
|
19104
|
+
disableElevation,
|
19105
|
+
fullWidth,
|
19106
|
+
orientation,
|
19107
|
+
variant
|
19108
|
+
} = ownerState;
|
19109
|
+
const slots = {
|
19110
|
+
root: ["root", variant, orientation, fullWidth && "fullWidth", disableElevation && "disableElevation", `color${capitalize(color2)}`],
|
19111
|
+
grouped: ["grouped", `grouped${capitalize(orientation)}`, `grouped${capitalize(variant)}`, `grouped${capitalize(variant)}${capitalize(orientation)}`, `grouped${capitalize(variant)}${capitalize(color2)}`, disabled && "disabled"],
|
19112
|
+
firstButton: ["firstButton"],
|
19113
|
+
lastButton: ["lastButton"],
|
19114
|
+
middleButton: ["middleButton"]
|
19115
|
+
};
|
19116
|
+
return composeClasses(slots, getButtonGroupUtilityClass, classes);
|
19117
|
+
};
|
19118
|
+
const ButtonGroupRoot = styled("div", {
|
19119
|
+
name: "MuiButtonGroup",
|
19120
|
+
slot: "Root",
|
19121
|
+
overridesResolver: overridesResolver$2
|
19122
|
+
})(memoTheme(({
|
19123
|
+
theme: theme2
|
19124
|
+
}) => ({
|
19125
|
+
display: "inline-flex",
|
19126
|
+
borderRadius: (theme2.vars || theme2).shape.borderRadius,
|
19127
|
+
variants: [{
|
19128
|
+
props: {
|
19129
|
+
variant: "contained"
|
19130
|
+
},
|
19131
|
+
style: {
|
19132
|
+
boxShadow: (theme2.vars || theme2).shadows[2]
|
19133
|
+
}
|
19134
|
+
}, {
|
19135
|
+
props: {
|
19136
|
+
disableElevation: true
|
19137
|
+
},
|
19138
|
+
style: {
|
19139
|
+
boxShadow: "none"
|
19140
|
+
}
|
19141
|
+
}, {
|
19142
|
+
props: {
|
19143
|
+
fullWidth: true
|
19144
|
+
},
|
19145
|
+
style: {
|
19146
|
+
width: "100%"
|
19147
|
+
}
|
19148
|
+
}, {
|
19149
|
+
props: {
|
19150
|
+
orientation: "vertical"
|
19151
|
+
},
|
19152
|
+
style: {
|
19153
|
+
flexDirection: "column",
|
19154
|
+
[`& .${buttonGroupClasses.lastButton},& .${buttonGroupClasses.middleButton}`]: {
|
19155
|
+
borderTopRightRadius: 0,
|
19156
|
+
borderTopLeftRadius: 0
|
19157
|
+
},
|
19158
|
+
[`& .${buttonGroupClasses.firstButton},& .${buttonGroupClasses.middleButton}`]: {
|
19159
|
+
borderBottomRightRadius: 0,
|
19160
|
+
borderBottomLeftRadius: 0
|
19161
|
+
}
|
19162
|
+
}
|
19163
|
+
}, {
|
19164
|
+
props: {
|
19165
|
+
orientation: "horizontal"
|
19166
|
+
},
|
19167
|
+
style: {
|
19168
|
+
[`& .${buttonGroupClasses.firstButton},& .${buttonGroupClasses.middleButton}`]: {
|
19169
|
+
borderTopRightRadius: 0,
|
19170
|
+
borderBottomRightRadius: 0
|
19171
|
+
},
|
19172
|
+
[`& .${buttonGroupClasses.lastButton},& .${buttonGroupClasses.middleButton}`]: {
|
19173
|
+
borderTopLeftRadius: 0,
|
19174
|
+
borderBottomLeftRadius: 0
|
19175
|
+
}
|
19176
|
+
}
|
19177
|
+
}, {
|
19178
|
+
props: {
|
19179
|
+
variant: "text",
|
19180
|
+
orientation: "horizontal"
|
19181
|
+
},
|
19182
|
+
style: {
|
19183
|
+
[`& .${buttonGroupClasses.firstButton},& .${buttonGroupClasses.middleButton}`]: {
|
19184
|
+
borderRight: theme2.vars ? `1px solid rgba(${theme2.vars.palette.common.onBackgroundChannel} / 0.23)` : `1px solid ${theme2.palette.mode === "light" ? "rgba(0, 0, 0, 0.23)" : "rgba(255, 255, 255, 0.23)"}`,
|
19185
|
+
[`&.${buttonGroupClasses.disabled}`]: {
|
19186
|
+
borderRight: `1px solid ${(theme2.vars || theme2).palette.action.disabled}`
|
19187
|
+
}
|
19188
|
+
}
|
19189
|
+
}
|
19190
|
+
}, {
|
19191
|
+
props: {
|
19192
|
+
variant: "text",
|
19193
|
+
orientation: "vertical"
|
19194
|
+
},
|
19195
|
+
style: {
|
19196
|
+
[`& .${buttonGroupClasses.firstButton},& .${buttonGroupClasses.middleButton}`]: {
|
19197
|
+
borderBottom: theme2.vars ? `1px solid rgba(${theme2.vars.palette.common.onBackgroundChannel} / 0.23)` : `1px solid ${theme2.palette.mode === "light" ? "rgba(0, 0, 0, 0.23)" : "rgba(255, 255, 255, 0.23)"}`,
|
19198
|
+
[`&.${buttonGroupClasses.disabled}`]: {
|
19199
|
+
borderBottom: `1px solid ${(theme2.vars || theme2).palette.action.disabled}`
|
19200
|
+
}
|
19201
|
+
}
|
19202
|
+
}
|
19203
|
+
}, ...Object.entries(theme2.palette).filter(createSimplePaletteValueFilter()).flatMap(([color2]) => [{
|
19204
|
+
props: {
|
19205
|
+
variant: "text",
|
19206
|
+
color: color2
|
19207
|
+
},
|
19208
|
+
style: {
|
19209
|
+
[`& .${buttonGroupClasses.firstButton},& .${buttonGroupClasses.middleButton}`]: {
|
19210
|
+
borderColor: theme2.vars ? `rgba(${theme2.vars.palette[color2].mainChannel} / 0.5)` : alpha(theme2.palette[color2].main, 0.5)
|
19211
|
+
}
|
19212
|
+
}
|
19213
|
+
}]), {
|
19214
|
+
props: {
|
19215
|
+
variant: "outlined",
|
19216
|
+
orientation: "horizontal"
|
19217
|
+
},
|
19218
|
+
style: {
|
19219
|
+
[`& .${buttonGroupClasses.firstButton},& .${buttonGroupClasses.middleButton}`]: {
|
19220
|
+
borderRightColor: "transparent",
|
19221
|
+
"&:hover": {
|
19222
|
+
borderRightColor: "currentColor"
|
19223
|
+
}
|
19224
|
+
},
|
19225
|
+
[`& .${buttonGroupClasses.lastButton},& .${buttonGroupClasses.middleButton}`]: {
|
19226
|
+
marginLeft: -1
|
19227
|
+
}
|
19228
|
+
}
|
19229
|
+
}, {
|
19230
|
+
props: {
|
19231
|
+
variant: "outlined",
|
19232
|
+
orientation: "vertical"
|
19233
|
+
},
|
19234
|
+
style: {
|
19235
|
+
[`& .${buttonGroupClasses.firstButton},& .${buttonGroupClasses.middleButton}`]: {
|
19236
|
+
borderBottomColor: "transparent",
|
19237
|
+
"&:hover": {
|
19238
|
+
borderBottomColor: "currentColor"
|
19239
|
+
}
|
19240
|
+
},
|
19241
|
+
[`& .${buttonGroupClasses.lastButton},& .${buttonGroupClasses.middleButton}`]: {
|
19242
|
+
marginTop: -1
|
19243
|
+
}
|
19244
|
+
}
|
19245
|
+
}, {
|
19246
|
+
props: {
|
19247
|
+
variant: "contained",
|
19248
|
+
orientation: "horizontal"
|
19249
|
+
},
|
19250
|
+
style: {
|
19251
|
+
[`& .${buttonGroupClasses.firstButton},& .${buttonGroupClasses.middleButton}`]: {
|
19252
|
+
borderRight: `1px solid ${(theme2.vars || theme2).palette.grey[400]}`,
|
19253
|
+
[`&.${buttonGroupClasses.disabled}`]: {
|
19254
|
+
borderRight: `1px solid ${(theme2.vars || theme2).palette.action.disabled}`
|
19255
|
+
}
|
19256
|
+
}
|
19257
|
+
}
|
19258
|
+
}, {
|
19259
|
+
props: {
|
19260
|
+
variant: "contained",
|
19261
|
+
orientation: "vertical"
|
19262
|
+
},
|
19263
|
+
style: {
|
19264
|
+
[`& .${buttonGroupClasses.firstButton},& .${buttonGroupClasses.middleButton}`]: {
|
19265
|
+
borderBottom: `1px solid ${(theme2.vars || theme2).palette.grey[400]}`,
|
19266
|
+
[`&.${buttonGroupClasses.disabled}`]: {
|
19267
|
+
borderBottom: `1px solid ${(theme2.vars || theme2).palette.action.disabled}`
|
19268
|
+
}
|
19269
|
+
}
|
19270
|
+
}
|
19271
|
+
}, ...Object.entries(theme2.palette).filter(createSimplePaletteValueFilter(["dark"])).map(([color2]) => ({
|
19272
|
+
props: {
|
19273
|
+
variant: "contained",
|
19274
|
+
color: color2
|
19275
|
+
},
|
19276
|
+
style: {
|
19277
|
+
[`& .${buttonGroupClasses.firstButton},& .${buttonGroupClasses.middleButton}`]: {
|
19278
|
+
borderColor: (theme2.vars || theme2).palette[color2].dark
|
19279
|
+
}
|
19280
|
+
}
|
19281
|
+
}))],
|
19282
|
+
[`& .${buttonGroupClasses.grouped}`]: {
|
19283
|
+
minWidth: 40,
|
19284
|
+
boxShadow: "none",
|
19285
|
+
props: {
|
19286
|
+
variant: "contained"
|
19287
|
+
},
|
19288
|
+
style: {
|
19289
|
+
"&:hover": {
|
19290
|
+
boxShadow: "none"
|
19291
|
+
}
|
19292
|
+
}
|
19293
|
+
}
|
19294
|
+
})));
|
19295
|
+
const ButtonGroup = /* @__PURE__ */ reactExports.forwardRef(function ButtonGroup2(inProps, ref) {
|
19296
|
+
const props = useDefaultProps({
|
19297
|
+
props: inProps,
|
19298
|
+
name: "MuiButtonGroup"
|
19299
|
+
});
|
19300
|
+
const {
|
19301
|
+
children,
|
19302
|
+
className,
|
19303
|
+
color: color2 = "primary",
|
19304
|
+
component = "div",
|
19305
|
+
disabled = false,
|
19306
|
+
disableElevation = false,
|
19307
|
+
disableFocusRipple = false,
|
19308
|
+
disableRipple = false,
|
19309
|
+
fullWidth = false,
|
19310
|
+
orientation = "horizontal",
|
19311
|
+
size = "medium",
|
19312
|
+
variant = "outlined",
|
19313
|
+
...other
|
19314
|
+
} = props;
|
19315
|
+
const ownerState = {
|
19316
|
+
...props,
|
19317
|
+
color: color2,
|
19318
|
+
component,
|
19319
|
+
disabled,
|
19320
|
+
disableElevation,
|
19321
|
+
disableFocusRipple,
|
19322
|
+
disableRipple,
|
19323
|
+
fullWidth,
|
19324
|
+
orientation,
|
19325
|
+
size,
|
19326
|
+
variant
|
19327
|
+
};
|
19328
|
+
const classes = useUtilityClasses$x(ownerState);
|
19329
|
+
const context = reactExports.useMemo(() => ({
|
19330
|
+
className: classes.grouped,
|
19331
|
+
color: color2,
|
19332
|
+
disabled,
|
19333
|
+
disableElevation,
|
19334
|
+
disableFocusRipple,
|
19335
|
+
disableRipple,
|
19336
|
+
fullWidth,
|
19337
|
+
size,
|
19338
|
+
variant
|
19339
|
+
}), [color2, disabled, disableElevation, disableFocusRipple, disableRipple, fullWidth, size, variant, classes.grouped]);
|
19340
|
+
const validChildren = getValidReactChildren(children);
|
19341
|
+
const childrenCount = validChildren.length;
|
19342
|
+
const getButtonPositionClassName = (index) => {
|
19343
|
+
const isFirstButton = index === 0;
|
19344
|
+
const isLastButton = index === childrenCount - 1;
|
19345
|
+
if (isFirstButton && isLastButton) {
|
19346
|
+
return "";
|
19347
|
+
}
|
19348
|
+
if (isFirstButton) {
|
19349
|
+
return classes.firstButton;
|
19350
|
+
}
|
19351
|
+
if (isLastButton) {
|
19352
|
+
return classes.lastButton;
|
19353
|
+
}
|
19354
|
+
return classes.middleButton;
|
19355
|
+
};
|
19356
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(ButtonGroupRoot, {
|
19357
|
+
as: component,
|
19358
|
+
role: "group",
|
19359
|
+
className: clsx(classes.root, className),
|
19360
|
+
ref,
|
19361
|
+
ownerState,
|
19362
|
+
...other,
|
19363
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ButtonGroupContext.Provider, {
|
19364
|
+
value: context,
|
19365
|
+
children: validChildren.map((child, index) => {
|
19366
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(ButtonGroupButtonContext.Provider, {
|
19367
|
+
value: getButtonPositionClassName(index),
|
19368
|
+
children: child
|
19369
|
+
}, index);
|
19370
|
+
})
|
19371
|
+
})
|
19372
|
+
});
|
19373
|
+
});
|
19073
19374
|
function getSwitchBaseUtilityClass(slot) {
|
19074
19375
|
return generateUtilityClass("PrivateSwitchBase", slot);
|
19075
19376
|
}
|
@@ -35852,11 +36153,75 @@ function EditModal({
|
|
35852
36153
|
}
|
35853
36154
|
);
|
35854
36155
|
}
|
36156
|
+
const applyOffsetToTime = (time, offsetMs) => {
|
36157
|
+
if (time === null) return null;
|
36158
|
+
return time + offsetMs / 1e3;
|
36159
|
+
};
|
36160
|
+
const applyOffsetToWord = (word, offsetMs) => {
|
36161
|
+
if (offsetMs === 0) return word;
|
36162
|
+
return {
|
36163
|
+
...word,
|
36164
|
+
start_time: applyOffsetToTime(word.start_time, offsetMs),
|
36165
|
+
end_time: applyOffsetToTime(word.end_time, offsetMs)
|
36166
|
+
};
|
36167
|
+
};
|
36168
|
+
const applyOffsetToSegment = (segment, offsetMs) => {
|
36169
|
+
if (offsetMs === 0) return segment;
|
36170
|
+
const adjustedWords = segment.words.map((word) => applyOffsetToWord(word, offsetMs));
|
36171
|
+
const validStartTimes = adjustedWords.map((w) => w.start_time).filter((t) => t !== null);
|
36172
|
+
const validEndTimes = adjustedWords.map((w) => w.end_time).filter((t) => t !== null);
|
36173
|
+
const segmentStartTime = validStartTimes.length > 0 ? Math.min(...validStartTimes) : null;
|
36174
|
+
const segmentEndTime = validEndTimes.length > 0 ? Math.max(...validEndTimes) : null;
|
36175
|
+
return {
|
36176
|
+
...segment,
|
36177
|
+
words: adjustedWords,
|
36178
|
+
start_time: segmentStartTime,
|
36179
|
+
end_time: segmentEndTime
|
36180
|
+
};
|
36181
|
+
};
|
36182
|
+
const applyOffsetToCorrectionData = (data, offsetMs) => {
|
36183
|
+
console.log(`[TIMING] applyOffsetToCorrectionData called with offset: ${offsetMs}ms`);
|
36184
|
+
if (offsetMs === 0) {
|
36185
|
+
console.log("[TIMING] Offset is 0, returning original data");
|
36186
|
+
return data;
|
36187
|
+
}
|
36188
|
+
if (data.corrected_segments.length > 0) {
|
36189
|
+
const firstSegment = data.corrected_segments[0];
|
36190
|
+
console.log(`[TIMING] First segment before offset - id: ${firstSegment.id}`);
|
36191
|
+
console.log(`[TIMING] - start_time: ${firstSegment.start_time}, end_time: ${firstSegment.end_time}`);
|
36192
|
+
if (firstSegment.words.length > 0) {
|
36193
|
+
const firstWord = firstSegment.words[0];
|
36194
|
+
const lastWord = firstSegment.words[firstSegment.words.length - 1];
|
36195
|
+
console.log(`[TIMING] - first word "${firstWord.text}" time: ${firstWord.start_time} -> ${firstWord.end_time}`);
|
36196
|
+
console.log(`[TIMING] - last word "${lastWord.text}" time: ${lastWord.start_time} -> ${lastWord.end_time}`);
|
36197
|
+
}
|
36198
|
+
}
|
36199
|
+
const result = {
|
36200
|
+
...data,
|
36201
|
+
corrected_segments: data.corrected_segments.map(
|
36202
|
+
(segment) => applyOffsetToSegment(segment, offsetMs)
|
36203
|
+
)
|
36204
|
+
};
|
36205
|
+
if (result.corrected_segments.length > 0) {
|
36206
|
+
const firstSegment = result.corrected_segments[0];
|
36207
|
+
console.log(`[TIMING] First segment AFTER offset - id: ${firstSegment.id}`);
|
36208
|
+
console.log(`[TIMING] - start_time: ${firstSegment.start_time}, end_time: ${firstSegment.end_time}`);
|
36209
|
+
if (firstSegment.words.length > 0) {
|
36210
|
+
const firstWord = firstSegment.words[0];
|
36211
|
+
const lastWord = firstSegment.words[firstSegment.words.length - 1];
|
36212
|
+
console.log(`[TIMING] - first word "${firstWord.text}" time: ${firstWord.start_time} -> ${firstWord.end_time}`);
|
36213
|
+
console.log(`[TIMING] - last word "${lastWord.text}" time: ${lastWord.start_time} -> ${lastWord.end_time}`);
|
36214
|
+
}
|
36215
|
+
}
|
36216
|
+
console.log(`[TIMING] Finished applying offset of ${offsetMs}ms to data`);
|
36217
|
+
return result;
|
36218
|
+
};
|
35855
36219
|
function PreviewVideoSection({
|
35856
36220
|
apiClient,
|
35857
36221
|
isModalOpen: isModalOpen2,
|
35858
36222
|
updatedData,
|
35859
|
-
videoRef
|
36223
|
+
videoRef,
|
36224
|
+
timingOffsetMs = 0
|
35860
36225
|
}) {
|
35861
36226
|
const [previewState, setPreviewState] = reactExports.useState({ status: "loading" });
|
35862
36227
|
reactExports.useEffect(() => {
|
@@ -35864,7 +36229,18 @@ function PreviewVideoSection({
|
|
35864
36229
|
const generatePreview = async () => {
|
35865
36230
|
setPreviewState({ status: "loading" });
|
35866
36231
|
try {
|
35867
|
-
|
36232
|
+
console.log(`[TIMING] PreviewVideoSection - Current timing offset: ${timingOffsetMs}ms`);
|
36233
|
+
const dataToPreview = timingOffsetMs !== 0 ? applyOffsetToCorrectionData(updatedData, timingOffsetMs) : updatedData;
|
36234
|
+
if (dataToPreview.corrected_segments.length > 0) {
|
36235
|
+
const firstSegment = dataToPreview.corrected_segments[0];
|
36236
|
+
console.log(`[TIMING] Preview - First segment id: ${firstSegment.id}`);
|
36237
|
+
console.log(`[TIMING] - start_time: ${firstSegment.start_time}, end_time: ${firstSegment.end_time}`);
|
36238
|
+
if (firstSegment.words.length > 0) {
|
36239
|
+
const firstWord = firstSegment.words[0];
|
36240
|
+
console.log(`[TIMING] - first word "${firstWord.text}" time: ${firstWord.start_time} -> ${firstWord.end_time}`);
|
36241
|
+
}
|
36242
|
+
}
|
36243
|
+
const response = await apiClient.generatePreviewVideo(dataToPreview);
|
35868
36244
|
if (response.status === "error") {
|
35869
36245
|
setPreviewState({
|
35870
36246
|
status: "error",
|
@@ -35893,7 +36269,7 @@ function PreviewVideoSection({
|
|
35893
36269
|
};
|
35894
36270
|
generatePreview();
|
35895
36271
|
}
|
35896
|
-
}, [isModalOpen2, apiClient, updatedData]);
|
36272
|
+
}, [isModalOpen2, apiClient, updatedData, timingOffsetMs]);
|
35897
36273
|
if (!apiClient) return null;
|
35898
36274
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { mb: 2 }, children: [
|
35899
36275
|
previewState.status === "loading" && /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 2, p: 2 }, children: [
|
@@ -35965,6 +36341,9 @@ const PlayArrowIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path"
|
|
35965
36341
|
const RedoIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
35966
36342
|
d: "M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7z"
|
35967
36343
|
}), "Redo");
|
36344
|
+
const TimerIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
36345
|
+
d: "M9 1h6v2H9zm10.03 6.39 1.42-1.42c-.43-.51-.9-.99-1.41-1.41l-1.42 1.42C16.07 4.74 14.12 4 12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9 9-4.03 9-9c0-2.12-.74-4.07-1.97-5.61M13 14h-2V8h2z"
|
36346
|
+
}), "Timer");
|
35968
36347
|
const UndoIcon = createSvgIcon(/* @__PURE__ */ jsxRuntimeExports.jsx("path", {
|
35969
36348
|
d: "M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8"
|
35970
36349
|
}), "Undo");
|
@@ -35990,7 +36369,8 @@ function ReviewChangesModal({
|
|
35990
36369
|
updatedData,
|
35991
36370
|
onSubmit,
|
35992
36371
|
apiClient,
|
35993
|
-
setModalSpacebarHandler
|
36372
|
+
setModalSpacebarHandler,
|
36373
|
+
timingOffsetMs = 0
|
35994
36374
|
}) {
|
35995
36375
|
const videoRef = reactExports.useRef(null);
|
35996
36376
|
reactExports.useEffect(() => {
|
@@ -36020,6 +36400,11 @@ function ReviewChangesModal({
|
|
36020
36400
|
setModalSpacebarHandler(void 0);
|
36021
36401
|
};
|
36022
36402
|
}, [open, setModalSpacebarHandler]);
|
36403
|
+
reactExports.useEffect(() => {
|
36404
|
+
if (open) {
|
36405
|
+
console.log(`[TIMING] ReviewChangesModal opened - timingOffsetMs: ${timingOffsetMs}ms`);
|
36406
|
+
}
|
36407
|
+
}, [open, timingOffsetMs]);
|
36023
36408
|
const differences = reactExports.useMemo(() => {
|
36024
36409
|
var _a, _b;
|
36025
36410
|
const diffs = [];
|
@@ -36180,24 +36565,33 @@ function ReviewChangesModal({
|
|
36180
36565
|
apiClient,
|
36181
36566
|
isModalOpen: open,
|
36182
36567
|
updatedData,
|
36183
|
-
videoRef
|
36568
|
+
videoRef,
|
36569
|
+
timingOffsetMs
|
36184
36570
|
}
|
36185
36571
|
),
|
36186
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
36187
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
36188
|
-
|
36189
|
-
"
|
36190
|
-
|
36191
|
-
|
36192
|
-
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { children: [
|
36193
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 1 }, children: [
|
36194
|
-
differences.length,
|
36195
|
-
" segment",
|
36196
|
-
differences.length !== 1 ? "s" : "",
|
36197
|
-
" modified:"
|
36572
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { p: 2, mt: 0 }, children: [
|
36573
|
+
timingOffsetMs !== 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(Typography, { variant: "body2", fontWeight: "bold", sx: { mt: 1 }, children: [
|
36574
|
+
"Global Timing Offset applied to all words: ",
|
36575
|
+
timingOffsetMs > 0 ? "+" : "",
|
36576
|
+
timingOffsetMs,
|
36577
|
+
"ms"
|
36198
36578
|
] }),
|
36199
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
36200
|
-
|
36579
|
+
differences.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { children: [
|
36580
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Typography, { color: "text.secondary", children: "No manual corrections detected. If everything looks good in the preview, click submit and the server will generate the final karaoke video." }),
|
36581
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Typography, { variant: "body2", color: "text.secondary", children: [
|
36582
|
+
"Total segments: ",
|
36583
|
+
updatedData.corrected_segments.length
|
36584
|
+
] })
|
36585
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { children: [
|
36586
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 1 }, children: [
|
36587
|
+
differences.length,
|
36588
|
+
" segment",
|
36589
|
+
differences.length !== 1 ? "s" : "",
|
36590
|
+
" modified:"
|
36591
|
+
] }),
|
36592
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Paper, { sx: { p: 2 }, children: differences.map(renderCompactDiff) })
|
36593
|
+
] })
|
36594
|
+
] })
|
36201
36595
|
]
|
36202
36596
|
}
|
36203
36597
|
),
|
@@ -36326,6 +36720,9 @@ const setupKeyboardHandlers = (state) => {
|
|
36326
36720
|
}
|
36327
36721
|
};
|
36328
36722
|
const handleKeyUp = (e) => {
|
36723
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
36724
|
+
return;
|
36725
|
+
}
|
36329
36726
|
resetModifierStates();
|
36330
36727
|
if (e.key === " " || e.code === "Space") {
|
36331
36728
|
e.preventDefault();
|
@@ -36555,6 +36952,8 @@ function Header({
|
|
36555
36952
|
onHandlerClick,
|
36556
36953
|
onFindReplace,
|
36557
36954
|
onEditAll,
|
36955
|
+
onTimingOffset,
|
36956
|
+
timingOffsetMs = 0,
|
36558
36957
|
onUndo,
|
36559
36958
|
onRedo,
|
36560
36959
|
canUndo,
|
@@ -36779,6 +37178,36 @@ function Header({
|
|
36779
37178
|
children: "Edit All"
|
36780
37179
|
}
|
36781
37180
|
),
|
37181
|
+
!isReadOnly && onTimingOffset && /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { display: "flex", alignItems: "center" }, children: [
|
37182
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
37183
|
+
Button,
|
37184
|
+
{
|
37185
|
+
variant: "outlined",
|
37186
|
+
size: "small",
|
37187
|
+
onClick: onTimingOffset,
|
37188
|
+
startIcon: /* @__PURE__ */ jsxRuntimeExports.jsx(TimerIcon, {}),
|
37189
|
+
color: timingOffsetMs !== 0 ? "secondary" : "primary",
|
37190
|
+
sx: { minWidth: "fit-content", height: "32px" },
|
37191
|
+
children: "Timing Offset"
|
37192
|
+
}
|
37193
|
+
),
|
37194
|
+
timingOffsetMs !== 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
37195
|
+
Typography,
|
37196
|
+
{
|
37197
|
+
variant: "body2",
|
37198
|
+
sx: {
|
37199
|
+
ml: 1,
|
37200
|
+
fontWeight: "bold",
|
37201
|
+
color: theme2.palette.secondary.main
|
37202
|
+
},
|
37203
|
+
children: [
|
37204
|
+
timingOffsetMs > 0 ? "+" : "",
|
37205
|
+
timingOffsetMs,
|
37206
|
+
"ms"
|
37207
|
+
]
|
37208
|
+
}
|
37209
|
+
)
|
37210
|
+
] }),
|
36782
37211
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
36783
37212
|
AudioPlayer,
|
36784
37213
|
{
|
@@ -37219,6 +37648,100 @@ function FindReplaceModal({
|
|
37219
37648
|
}
|
37220
37649
|
);
|
37221
37650
|
}
|
37651
|
+
function TimingOffsetModal({
|
37652
|
+
open,
|
37653
|
+
onClose,
|
37654
|
+
currentOffset,
|
37655
|
+
onApply
|
37656
|
+
}) {
|
37657
|
+
const [offsetMs, setOffsetMs] = reactExports.useState(currentOffset);
|
37658
|
+
reactExports.useEffect(() => {
|
37659
|
+
if (open) {
|
37660
|
+
setOffsetMs(currentOffset);
|
37661
|
+
}
|
37662
|
+
}, [open, currentOffset]);
|
37663
|
+
const handlePresetClick = (value) => {
|
37664
|
+
setOffsetMs((prev2) => prev2 + value);
|
37665
|
+
};
|
37666
|
+
const handleInputChange = (e) => {
|
37667
|
+
const value = e.target.value === "" ? 0 : parseInt(e.target.value, 10);
|
37668
|
+
if (!isNaN(value)) {
|
37669
|
+
setOffsetMs(value);
|
37670
|
+
}
|
37671
|
+
};
|
37672
|
+
const handleApply = () => {
|
37673
|
+
onApply(offsetMs);
|
37674
|
+
onClose();
|
37675
|
+
};
|
37676
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
37677
|
+
Dialog,
|
37678
|
+
{
|
37679
|
+
open,
|
37680
|
+
onClose,
|
37681
|
+
maxWidth: "sm",
|
37682
|
+
fullWidth: true,
|
37683
|
+
PaperProps: {
|
37684
|
+
sx: {
|
37685
|
+
overflowY: "visible"
|
37686
|
+
}
|
37687
|
+
},
|
37688
|
+
children: [
|
37689
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
37690
|
+
"Adjust Global Timing Offset",
|
37691
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(IconButton, { onClick: onClose, size: "small", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CloseIcon, {}) })
|
37692
|
+
] }),
|
37693
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { mb: 3, mt: 1 }, children: [
|
37694
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Typography, { variant: "body2", sx: { mb: 1 }, children: "Adjust the timing of all words in the transcription. Positive values delay the timing, negative values advance it." }),
|
37695
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Typography, { variant: "body2", sx: { fontStyle: "italic", mb: 2 }, children: "Note: This offset is applied globally but doesn't modify the original timestamps." }),
|
37696
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { display: "flex", alignItems: "center", mb: 2 }, children: [
|
37697
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Typography, { variant: "body1", sx: { mr: 2 }, children: "Offset:" }),
|
37698
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
37699
|
+
TextField,
|
37700
|
+
{
|
37701
|
+
value: offsetMs,
|
37702
|
+
onChange: handleInputChange,
|
37703
|
+
type: "number",
|
37704
|
+
variant: "outlined",
|
37705
|
+
size: "small",
|
37706
|
+
InputProps: {
|
37707
|
+
endAdornment: /* @__PURE__ */ jsxRuntimeExports.jsx(Typography, { variant: "body2", sx: { ml: 1 }, children: "ms" })
|
37708
|
+
},
|
37709
|
+
sx: { width: 120 }
|
37710
|
+
}
|
37711
|
+
)
|
37712
|
+
] }),
|
37713
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { display: "flex", flexDirection: "column", gap: 1 }, children: [
|
37714
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Typography, { variant: "body2", children: "Quick adjust:" }),
|
37715
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { display: "flex", justifyContent: "center", gap: 1 }, children: [
|
37716
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(ButtonGroup, { size: "small", children: [
|
37717
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { onClick: () => handlePresetClick(-100), children: "-100ms" }),
|
37718
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { onClick: () => handlePresetClick(-50), children: "-50ms" }),
|
37719
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { onClick: () => handlePresetClick(-10), children: "-10ms" })
|
37720
|
+
] }),
|
37721
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(ButtonGroup, { size: "small", children: [
|
37722
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { onClick: () => handlePresetClick(10), children: "+10ms" }),
|
37723
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { onClick: () => handlePresetClick(50), children: "+50ms" }),
|
37724
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { onClick: () => handlePresetClick(100), children: "+100ms" })
|
37725
|
+
] })
|
37726
|
+
] })
|
37727
|
+
] })
|
37728
|
+
] }) }),
|
37729
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogActions, { children: [
|
37730
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { onClick: onClose, children: "Cancel" }),
|
37731
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
37732
|
+
Button,
|
37733
|
+
{
|
37734
|
+
onClick: handleApply,
|
37735
|
+
variant: "contained",
|
37736
|
+
color: offsetMs === 0 ? "warning" : "primary",
|
37737
|
+
children: offsetMs === 0 ? "Remove Offset" : "Apply Offset"
|
37738
|
+
}
|
37739
|
+
)
|
37740
|
+
] })
|
37741
|
+
]
|
37742
|
+
}
|
37743
|
+
);
|
37744
|
+
}
|
37222
37745
|
const debugLog = false;
|
37223
37746
|
const MemoizedTranscriptionView = reactExports.memo(function MemoizedTranscriptionView2({
|
37224
37747
|
data,
|
@@ -37300,6 +37823,8 @@ const MemoizedHeader = reactExports.memo(function MemoizedHeader2({
|
|
37300
37823
|
onHandlerClick,
|
37301
37824
|
onFindReplace,
|
37302
37825
|
onEditAll,
|
37826
|
+
onTimingOffset,
|
37827
|
+
timingOffsetMs,
|
37303
37828
|
onUndo,
|
37304
37829
|
onRedo,
|
37305
37830
|
canUndo,
|
@@ -37322,6 +37847,8 @@ const MemoizedHeader = reactExports.memo(function MemoizedHeader2({
|
|
37322
37847
|
onHandlerClick,
|
37323
37848
|
onFindReplace,
|
37324
37849
|
onEditAll,
|
37850
|
+
onTimingOffset,
|
37851
|
+
timingOffsetMs,
|
37325
37852
|
onUndo,
|
37326
37853
|
onRedo,
|
37327
37854
|
canUndo,
|
@@ -37359,6 +37886,8 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37359
37886
|
const [isAddLyricsModalOpen, setIsAddLyricsModalOpen] = reactExports.useState(false);
|
37360
37887
|
const [isAnyModalOpen, setIsAnyModalOpen] = reactExports.useState(false);
|
37361
37888
|
const [isFindReplaceModalOpen, setIsFindReplaceModalOpen] = reactExports.useState(false);
|
37889
|
+
const [isTimingOffsetModalOpen, setIsTimingOffsetModalOpen] = reactExports.useState(false);
|
37890
|
+
const [timingOffsetMs, setTimingOffsetMs] = reactExports.useState(0);
|
37362
37891
|
const theme2 = useTheme();
|
37363
37892
|
const isMobile = useMediaQuery(theme2.breakpoints.down("md"));
|
37364
37893
|
const [history, setHistory] = reactExports.useState([initialData]);
|
@@ -37409,10 +37938,10 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37409
37938
|
}, [setIsShiftPressed, setIsCtrlPressed, isAnyModalOpen]);
|
37410
37939
|
reactExports.useEffect(() => {
|
37411
37940
|
const modalOpen = Boolean(
|
37412
|
-
modalContent || editModalSegment || isReviewModalOpen || isAddLyricsModalOpen || isFindReplaceModalOpen || isEditAllModalOpen
|
37941
|
+
modalContent || editModalSegment || isReviewModalOpen || isAddLyricsModalOpen || isFindReplaceModalOpen || isEditAllModalOpen || isTimingOffsetModalOpen
|
37413
37942
|
);
|
37414
37943
|
setIsAnyModalOpen(modalOpen);
|
37415
|
-
}, [modalContent, editModalSegment, isReviewModalOpen, isAddLyricsModalOpen, isFindReplaceModalOpen, isEditAllModalOpen]);
|
37944
|
+
}, [modalContent, editModalSegment, isReviewModalOpen, isAddLyricsModalOpen, isFindReplaceModalOpen, isEditAllModalOpen, isTimingOffsetModalOpen]);
|
37416
37945
|
const effectiveMode = isCtrlPressed ? "delete_word" : isShiftPressed ? "highlight" : interactionMode;
|
37417
37946
|
const handleFlash = reactExports.useCallback((type, info) => {
|
37418
37947
|
setFlashingType(null);
|
@@ -37564,13 +38093,25 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37564
38093
|
updateDataWithHistory(newData, "delete segment");
|
37565
38094
|
}, [data, updateDataWithHistory]);
|
37566
38095
|
const handleFinishReview = reactExports.useCallback(() => {
|
38096
|
+
console.log(`[TIMING] handleFinishReview - Current timing offset: ${timingOffsetMs}ms`);
|
37567
38097
|
setIsReviewModalOpen(true);
|
37568
|
-
}, []);
|
38098
|
+
}, [timingOffsetMs]);
|
37569
38099
|
const handleSubmitToServer = reactExports.useCallback(async () => {
|
37570
38100
|
if (!apiClient) return;
|
37571
38101
|
try {
|
37572
38102
|
if (debugLog) ;
|
37573
|
-
|
38103
|
+
console.log(`[TIMING] handleSubmitToServer - Current timing offset: ${timingOffsetMs}ms`);
|
38104
|
+
const dataToSubmit = timingOffsetMs !== 0 ? applyOffsetToCorrectionData(data, timingOffsetMs) : data;
|
38105
|
+
if (dataToSubmit.corrected_segments.length > 0) {
|
38106
|
+
const firstSegment = dataToSubmit.corrected_segments[0];
|
38107
|
+
console.log(`[TIMING] Submitting data - First segment id: ${firstSegment.id}`);
|
38108
|
+
console.log(`[TIMING] - start_time: ${firstSegment.start_time}, end_time: ${firstSegment.end_time}`);
|
38109
|
+
if (firstSegment.words.length > 0) {
|
38110
|
+
const firstWord = firstSegment.words[0];
|
38111
|
+
console.log(`[TIMING] - first word "${firstWord.text}" time: ${firstWord.start_time} -> ${firstWord.end_time}`);
|
38112
|
+
}
|
38113
|
+
}
|
38114
|
+
await apiClient.submitCorrections(dataToSubmit);
|
37574
38115
|
setIsReviewComplete(true);
|
37575
38116
|
setIsReviewModalOpen(false);
|
37576
38117
|
window.close();
|
@@ -37578,12 +38119,13 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37578
38119
|
console.error("Failed to submit corrections:", error);
|
37579
38120
|
alert("Failed to submit corrections. Please try again.");
|
37580
38121
|
}
|
37581
|
-
}, [apiClient, data]);
|
38122
|
+
}, [apiClient, data, timingOffsetMs]);
|
37582
38123
|
const handlePlaySegment = reactExports.useCallback((startTime) => {
|
37583
38124
|
if (window.seekAndPlayAudio) {
|
37584
|
-
|
38125
|
+
const adjustedStartTime = timingOffsetMs !== 0 ? startTime + timingOffsetMs / 1e3 : startTime;
|
38126
|
+
window.seekAndPlayAudio(adjustedStartTime);
|
37585
38127
|
}
|
37586
|
-
}, []);
|
38128
|
+
}, [timingOffsetMs]);
|
37587
38129
|
const handleResetCorrections = reactExports.useCallback(() => {
|
37588
38130
|
if (window.confirm("Are you sure you want to reset all corrections? This cannot be undone.")) {
|
37589
38131
|
clearSavedData(initialData);
|
@@ -37818,6 +38360,23 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37818
38360
|
uncorrected: () => handleFlash("uncorrected")
|
37819
38361
|
}), [handleFlash]);
|
37820
38362
|
const isAnyModalOpenMemo = reactExports.useMemo(() => isAnyModalOpen, [isAnyModalOpen]);
|
38363
|
+
const displayData = reactExports.useMemo(() => {
|
38364
|
+
return timingOffsetMs !== 0 ? applyOffsetToCorrectionData(data, timingOffsetMs) : data;
|
38365
|
+
}, [data, timingOffsetMs]);
|
38366
|
+
const handleOpenTimingOffsetModal = reactExports.useCallback(() => {
|
38367
|
+
setIsTimingOffsetModalOpen(true);
|
38368
|
+
}, []);
|
38369
|
+
const handleApplyTimingOffset = reactExports.useCallback((offsetMs) => {
|
38370
|
+
if (offsetMs !== timingOffsetMs) {
|
38371
|
+
console.log(`[TIMING] handleApplyTimingOffset: Changing offset from ${timingOffsetMs}ms to ${offsetMs}ms`);
|
38372
|
+
setTimingOffsetMs(offsetMs);
|
38373
|
+
} else {
|
38374
|
+
console.log(`[TIMING] handleApplyTimingOffset: Offset unchanged at ${offsetMs}ms`);
|
38375
|
+
}
|
38376
|
+
}, [timingOffsetMs]);
|
38377
|
+
reactExports.useEffect(() => {
|
38378
|
+
console.log(`[TIMING] timingOffsetMs changed to: ${timingOffsetMs}ms`);
|
38379
|
+
}, [timingOffsetMs]);
|
37821
38380
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: {
|
37822
38381
|
p: 1,
|
37823
38382
|
pb: 3,
|
@@ -37839,9 +38398,10 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37839
38398
|
onHandlerToggle: handleHandlerToggle,
|
37840
38399
|
isUpdatingHandlers,
|
37841
38400
|
onHandlerClick: handleHandlerClick,
|
37842
|
-
onAddLyrics: () => setIsAddLyricsModalOpen(true),
|
37843
38401
|
onFindReplace: () => setIsFindReplaceModalOpen(true),
|
37844
38402
|
onEditAll: handleEditAll,
|
38403
|
+
onTimingOffset: handleOpenTimingOffsetModal,
|
38404
|
+
timingOffsetMs,
|
37845
38405
|
onUndo: handleUndo,
|
37846
38406
|
onRedo: handleRedo,
|
37847
38407
|
canUndo,
|
@@ -37853,7 +38413,7 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37853
38413
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
37854
38414
|
MemoizedTranscriptionView,
|
37855
38415
|
{
|
37856
|
-
data,
|
38416
|
+
data: displayData,
|
37857
38417
|
mode: effectiveMode,
|
37858
38418
|
onElementClick: setModalContent,
|
37859
38419
|
onWordClick: handleWordClick,
|
@@ -37928,14 +38488,14 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37928
38488
|
setOriginalTranscribedGlobalSegment(null);
|
37929
38489
|
handleSetModalSpacebarHandler(void 0);
|
37930
38490
|
},
|
37931
|
-
segment: globalEditSegment,
|
38491
|
+
segment: globalEditSegment ? timingOffsetMs !== 0 ? applyOffsetToSegment(globalEditSegment, timingOffsetMs) : globalEditSegment : null,
|
37932
38492
|
segmentIndex: null,
|
37933
|
-
originalSegment: originalGlobalSegment,
|
38493
|
+
originalSegment: originalGlobalSegment ? timingOffsetMs !== 0 ? applyOffsetToSegment(originalGlobalSegment, timingOffsetMs) : originalGlobalSegment : null,
|
37934
38494
|
onSave: handleSaveGlobalEdit,
|
37935
38495
|
onPlaySegment: handlePlaySegment,
|
37936
38496
|
currentTime: currentAudioTime,
|
37937
38497
|
setModalSpacebarHandler: handleSetModalSpacebarHandler,
|
37938
|
-
originalTranscribedSegment: originalTranscribedGlobalSegment,
|
38498
|
+
originalTranscribedSegment: originalTranscribedGlobalSegment ? timingOffsetMs !== 0 ? applyOffsetToSegment(originalTranscribedGlobalSegment, timingOffsetMs) : originalTranscribedGlobalSegment : null,
|
37939
38499
|
isGlobal: true,
|
37940
38500
|
isLoading: isLoadingGlobalEdit
|
37941
38501
|
}
|
@@ -37948,9 +38508,9 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37948
38508
|
setEditModalSegment(null);
|
37949
38509
|
handleSetModalSpacebarHandler(void 0);
|
37950
38510
|
},
|
37951
|
-
segment: (editModalSegment == null ? void 0 : editModalSegment.segment)
|
38511
|
+
segment: (editModalSegment == null ? void 0 : editModalSegment.segment) ? timingOffsetMs !== 0 ? applyOffsetToSegment(editModalSegment.segment, timingOffsetMs) : editModalSegment.segment : null,
|
37952
38512
|
segmentIndex: (editModalSegment == null ? void 0 : editModalSegment.index) ?? null,
|
37953
|
-
originalSegment: (editModalSegment == null ? void 0 : editModalSegment.originalSegment)
|
38513
|
+
originalSegment: (editModalSegment == null ? void 0 : editModalSegment.originalSegment) ? timingOffsetMs !== 0 ? applyOffsetToSegment(editModalSegment.originalSegment, timingOffsetMs) : editModalSegment.originalSegment : null,
|
37954
38514
|
onSave: handleUpdateSegment,
|
37955
38515
|
onDelete: handleDeleteSegment,
|
37956
38516
|
onAddSegment: handleAddSegment,
|
@@ -37959,9 +38519,12 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37959
38519
|
onPlaySegment: handlePlaySegment,
|
37960
38520
|
currentTime: currentAudioTime,
|
37961
38521
|
setModalSpacebarHandler: handleSetModalSpacebarHandler,
|
37962
|
-
originalTranscribedSegment: (editModalSegment == null ? void 0 : editModalSegment.segment) && (editModalSegment == null ? void 0 : editModalSegment.index) !== null
|
37963
|
-
|
37964
|
-
|
38522
|
+
originalTranscribedSegment: (editModalSegment == null ? void 0 : editModalSegment.segment) && (editModalSegment == null ? void 0 : editModalSegment.index) !== null && originalData.original_segments ? (() => {
|
38523
|
+
const origSegment = originalData.original_segments.find(
|
38524
|
+
(s) => s.id === editModalSegment.segment.id
|
38525
|
+
) || null;
|
38526
|
+
return origSegment && timingOffsetMs !== 0 ? applyOffsetToSegment(origSegment, timingOffsetMs) : origSegment;
|
38527
|
+
})() : null
|
37965
38528
|
}
|
37966
38529
|
),
|
37967
38530
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
@@ -37973,7 +38536,8 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37973
38536
|
updatedData: data,
|
37974
38537
|
onSubmit: handleSubmitToServer,
|
37975
38538
|
apiClient,
|
37976
|
-
setModalSpacebarHandler: handleSetModalSpacebarHandler
|
38539
|
+
setModalSpacebarHandler: handleSetModalSpacebarHandler,
|
38540
|
+
timingOffsetMs
|
37977
38541
|
}
|
37978
38542
|
),
|
37979
38543
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
@@ -37993,6 +38557,15 @@ function LyricsAnalyzer({ data: initialData, onFileLoad, apiClient, isReadOnly,
|
|
37993
38557
|
onReplace: handleFindReplace,
|
37994
38558
|
data
|
37995
38559
|
}
|
38560
|
+
),
|
38561
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
38562
|
+
TimingOffsetModal,
|
38563
|
+
{
|
38564
|
+
open: isTimingOffsetModalOpen,
|
38565
|
+
onClose: () => setIsTimingOffsetModalOpen(false),
|
38566
|
+
currentOffset: timingOffsetMs,
|
38567
|
+
onApply: handleApplyTimingOffset
|
38568
|
+
}
|
37996
38569
|
)
|
37997
38570
|
] });
|
37998
38571
|
}
|
@@ -38348,4 +38921,4 @@ ReactDOM$1.createRoot(document.getElementById("root")).render(
|
|
38348
38921
|
/* @__PURE__ */ jsxRuntimeExports.jsx(App, {})
|
38349
38922
|
] })
|
38350
38923
|
);
|
38351
|
-
//# sourceMappingURL=index-
|
38924
|
+
//# sourceMappingURL=index-C5ftSgQo.js.map
|