Dee Ferdinand commited on
Commit
410447e
·
1 Parent(s): f4ac095

feat: init Dee Video Studio — HyperFrames cloud render for testimonial/teaser/trailer videos

Browse files

- 4 workflows: testimonial (75s), teaser (30s), trailer (60s), community (60s)
- 6 royalty-free Pixabay music tracks auto-selected by workflow
- WebSocket real-time render progress
- Dark-mode Studio UI with drag-drop upload
- HuggingFace Docker Space ready (port 7860)

Files changed (1) hide show
  1. workflows/index.js +92 -0
workflows/index.js ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function pick(media, preferVideo, idx) {
2
+ const v = media.filter(m => m.mime?.startsWith('video/'));
3
+ const i = media.filter(m => m.mime?.startsWith('image/'));
4
+ const pool = preferVideo ? (v.length ? v : i) : (i.length ? i : v);
5
+ return pool[idx % Math.max(pool.length, 1)] || media[idx % Math.max(media.length, 1)] || null;
6
+ }
7
+
8
+ const testimonial = {
9
+ meta: { name: 'Corporate Testimonial', description: '75s social proof video for corporate AI training.', format: '9:16', duration: 75, music: 'corporate', icon: '🏢' },
10
+ generateCuts(media, cfg) {
11
+ const { clientName = 'AI Training', trainerName = 'Dee Ferdinand' } = cfg;
12
+ return [
13
+ { start: 0, duration: 3, mediaFile: pick(media, true, 0), caption: clientName ? `${clientName} × AI Training` : 'AI Corporate Training', captionStyle: 'hook' },
14
+ { start: 3, duration: 2, mediaFile: pick(media, false, 0), caption: `${trainerName} · AI Corporate Trainer`, captionStyle: 'badge' },
15
+ { start: 5, duration: 5, mediaFile: pick(media, false, 1), caption: '1,000+ professionals trained since 2023', captionStyle: 'stat' },
16
+ { start: 10, duration: 5, mediaFile: pick(media, true, 1), caption: '80% hands-on · langsung praktek', captionStyle: 'default' },
17
+ { start: 15, duration: 8, mediaFile: pick(media, true, 2), caption: '"Saya pikir AI itu susah. Ternyata..."', captionStyle: 'default' },
18
+ { start: 23, duration: 4, mediaFile: pick(media, false, 2), caption: clientName ? `${clientName} · ${new Date().getFullYear()}` : null, captionStyle: 'badge' },
19
+ { start: 27, duration: 5, mediaFile: pick(media, true, 3), caption: 'Hands-on prompting. Real output.', captionStyle: 'default' },
20
+ { start: 32, duration: 4, mediaFile: pick(media, false, 3), caption: null },
21
+ { start: 36, duration: 7, mediaFile: pick(media, true, 4), caption: '"Sekarang saya bisa buat konten sendiri."', captionStyle: 'default' },
22
+ { start: 43, duration: 4, mediaFile: pick(media, false, 4), caption: null },
23
+ { start: 47, duration: 8, mediaFile: pick(media, true, 5), caption: 'Energi yang berbeda. Hasil yang nyata.', captionStyle: 'default' },
24
+ { start: 55, duration: 8, mediaFile: pick(media, true, 0), caption: 'Training AI untuk tim kamu?', captionStyle: 'hook' },
25
+ { start: 63, duration: 7, mediaFile: pick(media, false, 5), caption: 'DM · atau klik link di bio', captionStyle: 'default' },
26
+ ];
27
+ },
28
+ };
29
+
30
+ const teaser = {
31
+ meta: { name: 'Event Teaser', description: '30s fast-cut teaser for upcoming events.', format: '9:16', duration: 30, music: 'energetic', icon: '⚡' },
32
+ generateCuts(media, cfg) {
33
+ const { clientName = 'Next Event' } = cfg;
34
+ const m = media;
35
+ return [
36
+ { start: 0, duration: 2, mediaFile: pick(m,true,0), caption: 'COMING SOON', captionStyle: 'hook' },
37
+ { start: 2, duration: 2, mediaFile: pick(m,false,1), caption: null },
38
+ { start: 4, duration: 2, mediaFile: pick(m,true,1), caption: clientName, captionStyle: 'badge' },
39
+ { start: 6, duration: 2, mediaFile: pick(m,false,2), caption: null },
40
+ { start: 8, duration: 2, mediaFile: pick(m,true,2), caption: 'AI Training', captionStyle: 'default' },
41
+ { start: 10, duration: 2, mediaFile: pick(m,false,3), caption: null },
42
+ { start: 12, duration: 2, mediaFile: pick(m,true,3), caption: 'Hands-on. Real tools.', captionStyle: 'default' },
43
+ { start: 14, duration: 3, mediaFile: pick(m,true,0), caption: 'Real results. Real fast.', captionStyle: 'hook' },
44
+ { start: 17, duration: 3, mediaFile: pick(m,false,4), caption: null },
45
+ { start: 20, duration: 3, mediaFile: pick(m,true,0), caption: 'Save your spot. Link in bio.', captionStyle: 'default' },
46
+ ];
47
+ },
48
+ };
49
+
50
+ const trailer = {
51
+ meta: { name: 'Cinematic Trailer', description: '60s cinematic event recap or brand trailer.', format: '9:16', duration: 60, music: 'cinematic', icon: '🎬' },
52
+ generateCuts(media, cfg) {
53
+ const { clientName = '', trainerName = 'Dee Ferdinand' } = cfg;
54
+ const m = media;
55
+ return [
56
+ { start: 0, duration: 5, mediaFile: pick(m,true,0), caption: 'Ini bukan teori.', captionStyle: 'hook' },
57
+ { start: 5, duration: 4, mediaFile: pick(m,false,0), caption: 'Ini yang benar-benar terjadi.', captionStyle: 'default' },
58
+ { start: 9, duration: 4, mediaFile: pick(m,true,1), caption: clientName || null, captionStyle: 'badge' },
59
+ { start: 13, duration: 4, mediaFile: pick(m,false,1), caption: null },
60
+ { start: 17, duration: 5, mediaFile: pick(m,true,2), caption: 'Prompt. Praktek. Hasil.', captionStyle: 'default' },
61
+ { start: 22, duration: 4, mediaFile: pick(m,false,2), caption: null },
62
+ { start: 26, duration: 5, mediaFile: pick(m,true,3), caption: '"Saya tidak sangka bisa."', captionStyle: 'default' },
63
+ { start: 31, duration: 4, mediaFile: pick(m,false,3), caption: null },
64
+ { start: 35, duration: 5, mediaFile: pick(m,true,0), caption: '1,000+ professionals trained', captionStyle: 'stat' },
65
+ { start: 40, duration: 5, mediaFile: pick(m,true,4), caption: null },
66
+ { start: 45, duration: 5, mediaFile: pick(m,false,0), caption: `${trainerName} · AI Corporate Trainer`, captionStyle: 'brand' },
67
+ { start: 50, duration: 5, mediaFile: pick(m,true,1), caption: 'Training AI untuk tim kamu?', captionStyle: 'hook' },
68
+ ];
69
+ },
70
+ };
71
+
72
+ const community = {
73
+ meta: { name: 'Community Story', description: '60s warm documentary for community/church sessions.', format: '9:16', duration: 60, music: 'warm', icon: '🤝' },
74
+ generateCuts(media, cfg) {
75
+ const { clientName = 'Community Training', trainerName = 'Dee Ferdinand' } = cfg;
76
+ const m = media;
77
+ return [
78
+ { start: 0, duration: 4, mediaFile: pick(m,false,0), caption: 'AI bukan cuma untuk korporat.', captionStyle: 'hook' },
79
+ { start: 4, duration: 5, mediaFile: pick(m,true,0), caption: clientName, captionStyle: 'badge' },
80
+ { start: 9, duration: 5, mediaFile: pick(m,false,1), caption: 'Guru. Ibu rumah tangga. Mahasiswa.', captionStyle: 'default' },
81
+ { start: 14, duration: 5, mediaFile: pick(m,true,1), caption: null },
82
+ { start: 19, duration: 5, mediaFile: pick(m,false,2), caption: 'Semua orang bisa belajar AI.', captionStyle: 'default' },
83
+ { start: 24, duration: 8, mediaFile: pick(m,true,2), caption: '"Saya tidak sangka bisa."', captionStyle: 'default' },
84
+ { start: 32, duration: 5, mediaFile: pick(m,false,3), caption: null },
85
+ { start: 37, duration: 5, mediaFile: pick(m,true,3), caption: 'Belajar bersama. Tumbuh bersama.', captionStyle: 'default' },
86
+ { start: 42, duration: 5, mediaFile: pick(m,false,0), caption: `${trainerName} · ${new Date().getFullYear()}`, captionStyle: 'brand' },
87
+ { start: 47, duration: 5, mediaFile: pick(m,true,0), caption: 'Training AI untuk komunitas kamu?', captionStyle: 'hook' },
88
+ ];
89
+ },
90
+ };
91
+
92
+ export const WORKFLOWS = { testimonial, teaser, trailer, community };