@twick/studio 0.15.25 → 0.15.26
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.
- package/dist/components/properties/generate-captions.d.ts +1 -1
- package/dist/hooks/use-generate-captions.d.ts +1 -1
- package/dist/hooks/use-studio-operation.d.ts +0 -2
- package/dist/index.js +56 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +56 -17
- package/dist/index.mjs.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +15 -15
|
@@ -8,7 +8,7 @@ export declare function GenerateCaptionsPanel({ selectedElement, addCaptionsToTi
|
|
|
8
8
|
e: number;
|
|
9
9
|
t: string;
|
|
10
10
|
}[]) => void;
|
|
11
|
-
onGenerateCaptions: (videoElement: VideoElement) => Promise<string | null>;
|
|
11
|
+
onGenerateCaptions: (videoElement: VideoElement, language?: string, wordsPerPhrase?: number) => Promise<string | null>;
|
|
12
12
|
getCaptionstatus: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;
|
|
13
13
|
pollingIntervalMs?: number;
|
|
14
14
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,7 +2,7 @@ import { VideoElement } from '@twick/timeline';
|
|
|
2
2
|
import { ICaptionGenerationPollingResponse, StudioConfig, CaptionEntry } from '../types';
|
|
3
3
|
|
|
4
4
|
declare const useGenerateCaptions: (studioConfig?: StudioConfig) => {
|
|
5
|
-
onGenerateCaptions: (videoElement: VideoElement) => Promise<string | null>;
|
|
5
|
+
onGenerateCaptions: (videoElement: VideoElement, language?: string, wordsPerPhrase?: number) => Promise<string | null>;
|
|
6
6
|
addCaptionsToTimeline: (captions: CaptionEntry[]) => void;
|
|
7
7
|
getCaptionstatus: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;
|
|
8
8
|
pollingIntervalMs: number;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { VideoElement } from '@twick/timeline';
|
|
2
1
|
import { ICaptionGenerationPollingResponse, StudioConfig, CaptionEntry } from '../types';
|
|
3
2
|
|
|
4
3
|
declare const useStudioOperation: (studioConfig?: StudioConfig) => {
|
|
@@ -8,7 +7,6 @@ declare const useStudioOperation: (studioConfig?: StudioConfig) => {
|
|
|
8
7
|
onNewProject: () => void;
|
|
9
8
|
onExportCaptions: (format: "srt" | "vtt") => Promise<void>;
|
|
10
9
|
onExportChapters: (format: "youtube" | "json") => Promise<void>;
|
|
11
|
-
onGenerateCaptions: (videoElement: VideoElement) => Promise<string | null>;
|
|
12
10
|
addCaptionsToTimeline: (captions: CaptionEntry[]) => void;
|
|
13
11
|
getCaptionstatus: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;
|
|
14
12
|
};
|
package/dist/index.js
CHANGED
|
@@ -3028,10 +3028,10 @@ const TEXT_STYLE_PRESETS = [
|
|
|
3028
3028
|
applyBackground: false
|
|
3029
3029
|
},
|
|
3030
3030
|
{
|
|
3031
|
-
id: "
|
|
3032
|
-
label: "
|
|
3031
|
+
id: "bold-caption",
|
|
3032
|
+
label: "Bold Caption",
|
|
3033
3033
|
description: "Bold white with strong outline",
|
|
3034
|
-
fontFamily: VideoEditor.AVAILABLE_TEXT_FONTS.
|
|
3034
|
+
fontFamily: VideoEditor.AVAILABLE_TEXT_FONTS.ROBOTO,
|
|
3035
3035
|
fontSize: 34,
|
|
3036
3036
|
fontWeight: 700,
|
|
3037
3037
|
textColor: "#FFFFFF",
|
|
@@ -3131,7 +3131,7 @@ const TEXT_STYLE_PRESETS = [
|
|
|
3131
3131
|
id: "cta-pill",
|
|
3132
3132
|
label: "CTA Pill",
|
|
3133
3133
|
description: "Call-to-action pill",
|
|
3134
|
-
fontFamily: VideoEditor.AVAILABLE_TEXT_FONTS.
|
|
3134
|
+
fontFamily: VideoEditor.AVAILABLE_TEXT_FONTS.LUCKIEST_GUY,
|
|
3135
3135
|
fontSize: 28,
|
|
3136
3136
|
fontWeight: 700,
|
|
3137
3137
|
textColor: "#FFFFFF",
|
|
@@ -6943,6 +6943,8 @@ function GenerateCaptionsPanel({
|
|
|
6943
6943
|
const [isGenerating, setIsGenerating] = react.useState(false);
|
|
6944
6944
|
const [pollingStatus, setPollingStatus] = react.useState("idle");
|
|
6945
6945
|
const [errorMessage, setErrorMessage] = react.useState(null);
|
|
6946
|
+
const [selectedLanguage, setSelectedLanguage] = react.useState("auto");
|
|
6947
|
+
const [wordsPerPhrase, setWordsPerPhrase] = react.useState(4);
|
|
6946
6948
|
const pollingIntervalRef = react.useRef(null);
|
|
6947
6949
|
const currentReqIdRef = react.useRef(null);
|
|
6948
6950
|
react.useEffect(() => {
|
|
@@ -7003,7 +7005,12 @@ function GenerateCaptionsPanel({
|
|
|
7003
7005
|
setPollingStatus("polling");
|
|
7004
7006
|
const videoElement = selectedElement;
|
|
7005
7007
|
try {
|
|
7006
|
-
const
|
|
7008
|
+
const language = selectedLanguage === "auto" ? void 0 : selectedLanguage;
|
|
7009
|
+
const reqId = await onGenerateCaptions(
|
|
7010
|
+
videoElement,
|
|
7011
|
+
language,
|
|
7012
|
+
wordsPerPhrase
|
|
7013
|
+
);
|
|
7007
7014
|
if (!reqId) {
|
|
7008
7015
|
setPollingStatus("error");
|
|
7009
7016
|
setIsGenerating(false);
|
|
@@ -7062,6 +7069,46 @@ function GenerateCaptionsPanel({
|
|
|
7062
7069
|
/* @__PURE__ */ jsxRuntime.jsx(Volume2, { className: "empty-state-icon" }),
|
|
7063
7070
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "empty-state-text", children: "Audio detected! You can now generate captions" })
|
|
7064
7071
|
] }) }) }),
|
|
7072
|
+
!isLoading && containsAudio === true && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "panel-section", children: [
|
|
7073
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "label-dark", htmlFor: "caption-language", children: "Audio Language" }),
|
|
7074
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7075
|
+
"select",
|
|
7076
|
+
{
|
|
7077
|
+
id: "caption-language",
|
|
7078
|
+
className: "select-dark",
|
|
7079
|
+
value: selectedLanguage,
|
|
7080
|
+
onChange: (e) => setSelectedLanguage(e.target.value),
|
|
7081
|
+
children: [
|
|
7082
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "auto", children: "Auto (detect)" }),
|
|
7083
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "english", children: "English" }),
|
|
7084
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "italian", children: "Italian" }),
|
|
7085
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "spanish", children: "Spanish" }),
|
|
7086
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "portuguese", children: "Portuguese" }),
|
|
7087
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "french", children: "French" }),
|
|
7088
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "german", children: "German" }),
|
|
7089
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "turkish", children: "Turkish" }),
|
|
7090
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "indonesian", children: "Indonesian" }),
|
|
7091
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "hindi", children: "Hindi" })
|
|
7092
|
+
]
|
|
7093
|
+
}
|
|
7094
|
+
)
|
|
7095
|
+
] }),
|
|
7096
|
+
!isLoading && containsAudio === true && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "panel-section", children: [
|
|
7097
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "label-dark", htmlFor: "caption-words-per-phrase", children: "Words per phrase" }),
|
|
7098
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7099
|
+
"select",
|
|
7100
|
+
{
|
|
7101
|
+
id: "caption-words-per-phrase",
|
|
7102
|
+
className: "select-dark",
|
|
7103
|
+
value: String(wordsPerPhrase),
|
|
7104
|
+
onChange: (e) => setWordsPerPhrase(Number(e.target.value) || 4),
|
|
7105
|
+
children: Array.from({ length: 10 }).map((_, index) => {
|
|
7106
|
+
const value = index + 1;
|
|
7107
|
+
return /* @__PURE__ */ jsxRuntime.jsx("option", { value, children: value }, value);
|
|
7108
|
+
})
|
|
7109
|
+
}
|
|
7110
|
+
)
|
|
7111
|
+
] }),
|
|
7065
7112
|
!isLoading && isGenerating && pollingStatus === "polling" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "panel-section", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "empty-state", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "empty-state-content", children: [
|
|
7066
7113
|
/* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { className: "empty-state-icon animate-spin" }),
|
|
7067
7114
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "empty-state-text", children: "Generating captions... Please wait" })
|
|
@@ -7597,15 +7644,6 @@ const useStudioOperation = (studioConfig) => {
|
|
|
7597
7644
|
const fileName = `${(projectName || "chapters").replace(/\.json$/i, "")}.${format === "youtube" ? "txt" : "json"}`;
|
|
7598
7645
|
await saveAsFile(content, "text/plain", fileName);
|
|
7599
7646
|
};
|
|
7600
|
-
const onGenerateCaptions = async (videoElement) => {
|
|
7601
|
-
if (studioConfig == null ? void 0 : studioConfig.captionGenerationService) {
|
|
7602
|
-
const service = studioConfig.captionGenerationService;
|
|
7603
|
-
const reqId = await service.generateCaptions(videoElement, present);
|
|
7604
|
-
return reqId;
|
|
7605
|
-
}
|
|
7606
|
-
alert("Generate captions not supported in demo mode");
|
|
7607
|
-
return null;
|
|
7608
|
-
};
|
|
7609
7647
|
const addCaptionsToTimeline = (captions) => {
|
|
7610
7648
|
var _a;
|
|
7611
7649
|
const updatedProjectJSON = (_a = studioConfig == null ? void 0 : studioConfig.captionGenerationService) == null ? void 0 : _a.updateProjectWithCaptions(captions);
|
|
@@ -7630,7 +7668,6 @@ const useStudioOperation = (studioConfig) => {
|
|
|
7630
7668
|
onNewProject,
|
|
7631
7669
|
onExportCaptions,
|
|
7632
7670
|
onExportChapters,
|
|
7633
|
-
onGenerateCaptions,
|
|
7634
7671
|
addCaptionsToTimeline,
|
|
7635
7672
|
getCaptionstatus
|
|
7636
7673
|
};
|
|
@@ -7739,12 +7776,14 @@ function TwickStudio({ studioConfig }) {
|
|
|
7739
7776
|
const useGenerateCaptions = (studioConfig) => {
|
|
7740
7777
|
var _a;
|
|
7741
7778
|
const { editor, present } = timeline.useTimelineContext();
|
|
7742
|
-
const onGenerateCaptions = async (videoElement) => {
|
|
7779
|
+
const onGenerateCaptions = async (videoElement, language, wordsPerPhrase) => {
|
|
7743
7780
|
if (studioConfig == null ? void 0 : studioConfig.captionGenerationService) {
|
|
7744
7781
|
const service = studioConfig.captionGenerationService;
|
|
7745
7782
|
const reqId = await service.generateCaptions(
|
|
7746
7783
|
videoElement,
|
|
7747
|
-
present
|
|
7784
|
+
present,
|
|
7785
|
+
language,
|
|
7786
|
+
wordsPerPhrase
|
|
7748
7787
|
);
|
|
7749
7788
|
return reqId;
|
|
7750
7789
|
}
|