mulmocast 2.3.1 → 2.4.0
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/README.md +99 -43
- package/assets/html/tailwind.html +1 -0
- package/assets/html/tailwind_animated.html +259 -0
- package/lib/actions/image_agents.js +23 -2
- package/lib/actions/images.js +2 -2
- package/lib/agents/combine_audio_files_agent.js +5 -0
- package/lib/methods/mulmo_beat.d.ts +7 -0
- package/lib/methods/mulmo_beat.js +18 -0
- package/lib/types/schema.d.ts +23 -0
- package/lib/types/schema.js +10 -0
- package/lib/utils/context.d.ts +8 -0
- package/lib/utils/ffmpeg_utils.d.ts +10 -0
- package/lib/utils/ffmpeg_utils.js +27 -0
- package/lib/utils/file.d.ts +1 -0
- package/lib/utils/file.js +6 -0
- package/lib/utils/html_render.d.ts +11 -0
- package/lib/utils/html_render.js +84 -34
- package/lib/utils/image_plugins/html_tailwind.js +78 -6
- package/lib/utils/mulmo_config.d.ts +5 -5
- package/lib/utils/mulmo_config.js +7 -40
- package/package.json +3 -3
- package/scripts/test/test_html_animation.json +563 -0
- package/scripts/test/test_vocab_animation.json +226 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$mulmocast": {
|
|
3
|
+
"version": "1.1"
|
|
4
|
+
},
|
|
5
|
+
"lang": "en",
|
|
6
|
+
"title": "Vocabulary: serendipity",
|
|
7
|
+
"canvasSize": {
|
|
8
|
+
"width": 720,
|
|
9
|
+
"height": 1280
|
|
10
|
+
},
|
|
11
|
+
"speechParams": {
|
|
12
|
+
"speakers": {
|
|
13
|
+
"Presenter": {
|
|
14
|
+
"voiceId": "shimmer",
|
|
15
|
+
"displayName": {
|
|
16
|
+
"en": "Presenter"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"beats": [
|
|
22
|
+
{
|
|
23
|
+
"id": "audio_intro",
|
|
24
|
+
"speaker": "Presenter",
|
|
25
|
+
"text": "serendipity.",
|
|
26
|
+
"duration": 3,
|
|
27
|
+
"image": {
|
|
28
|
+
"type": "html_tailwind",
|
|
29
|
+
"html": "<div class='h-full bg-slate-900'></div>"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "word_display",
|
|
34
|
+
"speaker": "Presenter",
|
|
35
|
+
"text": "serendipity.",
|
|
36
|
+
"duration": 4,
|
|
37
|
+
"image": {
|
|
38
|
+
"type": "html_tailwind",
|
|
39
|
+
"html": [
|
|
40
|
+
"<div class='h-full flex flex-col items-center justify-center bg-gradient-to-br from-slate-900 to-indigo-950'>",
|
|
41
|
+
" <p id='phonetic' class='text-2xl text-indigo-300 font-mono mb-4' style='opacity:0'>/ˌser.ənˈdɪp.ɪ.ti/</p>",
|
|
42
|
+
" <h1 id='word' class='text-5xl font-bold text-white tracking-wide' style='opacity:0'>serendipity</h1>",
|
|
43
|
+
" <div id='underline' class='h-1 bg-gradient-to-r from-cyan-400 to-indigo-400 mt-6 rounded' style='width:0'></div>",
|
|
44
|
+
"</div>",
|
|
45
|
+
"<script>",
|
|
46
|
+
"function render(frame, totalFrames, fps) {",
|
|
47
|
+
" var word = document.getElementById('word');",
|
|
48
|
+
" word.style.opacity = interpolate(frame, [0, fps * 0.4], [0, 1]);",
|
|
49
|
+
" word.style.transform = 'scale(' + interpolateWithEasing(frame, [0, fps * 0.4], [0.9, 1], Easing.easeOut) + ')';",
|
|
50
|
+
" document.getElementById('phonetic').style.opacity = interpolate(frame, [fps * 0.3, fps * 0.7], [0, 1]);",
|
|
51
|
+
" document.getElementById('underline').style.width = interpolateWithEasing(frame, [fps * 0.5, fps * 1.2], [0, 300], Easing.easeInOut) + 'px';",
|
|
52
|
+
"}",
|
|
53
|
+
"</script>"
|
|
54
|
+
],
|
|
55
|
+
"animation": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "examples",
|
|
60
|
+
"speaker": "Presenter",
|
|
61
|
+
"text": "The discovery of penicillin was a moment of serendipity.",
|
|
62
|
+
"image": {
|
|
63
|
+
"type": "html_tailwind",
|
|
64
|
+
"html": [
|
|
65
|
+
"<div class='h-full flex flex-col justify-start pt-12 bg-slate-900 px-8'>",
|
|
66
|
+
" <h2 class='text-3xl font-bold text-indigo-300 mb-8'>Example Sentences</h2>",
|
|
67
|
+
" <div id='s0' class='mb-6 p-5 bg-slate-800 rounded-xl border-l-4 border-cyan-400' style='opacity:0; transform: translateX(-30px)'>",
|
|
68
|
+
" <p class='text-3xl text-white leading-relaxed'>The discovery of penicillin was a moment of <span class='text-cyan-400 font-semibold'>serendipity</span>.</p>",
|
|
69
|
+
" </div>",
|
|
70
|
+
" <div id='s1' class='mb-6 p-5 bg-slate-800 rounded-xl border-l-4 border-indigo-400' style='opacity:0; transform: translateX(-30px)'>",
|
|
71
|
+
" <p class='text-3xl text-white leading-relaxed'>She found the perfect dress by pure <span class='text-indigo-400 font-semibold'>serendipity</span>.</p>",
|
|
72
|
+
" </div>",
|
|
73
|
+
" <div id='s2' class='mb-6 p-5 bg-slate-800 rounded-xl border-l-4 border-purple-400' style='opacity:0; transform: translateX(-30px)'>",
|
|
74
|
+
" <p class='text-3xl text-white leading-relaxed'><span class='text-purple-400 font-semibold'>Serendipity</span> led him to his future business partner at a coffee shop.</p>",
|
|
75
|
+
" </div>",
|
|
76
|
+
"</div>",
|
|
77
|
+
"<script>",
|
|
78
|
+
"function render(frame, totalFrames, fps) {",
|
|
79
|
+
" var showAt = [30, 159, 264];",
|
|
80
|
+
" for (var i = 0; i < 3; i++) {",
|
|
81
|
+
" var el = document.getElementById('s' + i);",
|
|
82
|
+
" var start = showAt[i];",
|
|
83
|
+
" el.style.opacity = interpolateWithEasing(frame, [start, start + 15], [0, 1], Easing.easeOut);",
|
|
84
|
+
" el.style.transform = 'translateX(' + interpolateWithEasing(frame, [start, start + 15], [-30, 0], Easing.easeOut) + 'px)';",
|
|
85
|
+
" }",
|
|
86
|
+
"}",
|
|
87
|
+
"</script>"
|
|
88
|
+
],
|
|
89
|
+
"animation": true
|
|
90
|
+
},
|
|
91
|
+
"duration": 13.1
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": "example_vo2",
|
|
95
|
+
"speaker": "Presenter",
|
|
96
|
+
"text": "She found the perfect dress by pure serendipity.",
|
|
97
|
+
"image": {
|
|
98
|
+
"type": "voice_over",
|
|
99
|
+
"startAt": 4.3
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"id": "example_vo3",
|
|
104
|
+
"speaker": "Presenter",
|
|
105
|
+
"text": "Serendipity led him to his future business partner at a coffee shop.",
|
|
106
|
+
"image": {
|
|
107
|
+
"type": "voice_over",
|
|
108
|
+
"startAt": 7.8
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "explanation",
|
|
113
|
+
"speaker": "Presenter",
|
|
114
|
+
"text": "Serendipity means the occurrence of events by chance in a happy or beneficial way. It describes finding something good without looking for it.",
|
|
115
|
+
"duration": 12,
|
|
116
|
+
"image": {
|
|
117
|
+
"type": "html_tailwind",
|
|
118
|
+
"html": [
|
|
119
|
+
"<div class='h-full flex flex-col justify-start pt-12 bg-slate-900 px-8'>",
|
|
120
|
+
" <h2 class='text-3xl font-bold text-indigo-300 mb-8'>Meaning</h2>",
|
|
121
|
+
" <div id='en-block' class='mb-6 p-6 bg-slate-800 rounded-xl' style='opacity:0'>",
|
|
122
|
+
" <p class='text-2xl text-cyan-400 font-mono mb-2'>English</p>",
|
|
123
|
+
" <p class='text-3xl text-white leading-relaxed'>Serendipity means the occurrence of events by chance in a happy or beneficial way. It describes finding something good without looking for it.</p>",
|
|
124
|
+
" </div>",
|
|
125
|
+
" <div id='ja-block' class='p-6 bg-slate-800 rounded-xl' style='opacity:0'>",
|
|
126
|
+
" <p class='text-2xl text-indigo-400 font-mono mb-2'>日本語</p>",
|
|
127
|
+
" <p class='text-2xl text-slate-200 leading-relaxed'><span class='text-indigo-300 font-semibold'>セレンディピティ</span>とは、偶然の幸運な発見や出会いのこと。探していないのに、思いがけず良いものを見つけることを意味します。</p>",
|
|
128
|
+
" </div>",
|
|
129
|
+
"</div>",
|
|
130
|
+
"<script>",
|
|
131
|
+
"function render(frame, totalFrames, fps) {",
|
|
132
|
+
" var en = document.getElementById('en-block');",
|
|
133
|
+
" en.style.opacity = interpolate(frame, [0, 15], [0, 1]);",
|
|
134
|
+
" en.style.transform = 'translateY(' + interpolateWithEasing(frame, [0, 15], [15, 0], Easing.easeOut) + 'px)';",
|
|
135
|
+
" var ja = document.getElementById('ja-block');",
|
|
136
|
+
" ja.style.opacity = interpolate(frame, [280, 295], [0, 1]);",
|
|
137
|
+
" ja.style.transform = 'translateY(' + interpolateWithEasing(frame, [280, 295], [15, 0], Easing.easeOut) + 'px)';",
|
|
138
|
+
"}",
|
|
139
|
+
"</script>"
|
|
140
|
+
],
|
|
141
|
+
"animation": true
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"id": "review_1",
|
|
146
|
+
"speaker": "Presenter",
|
|
147
|
+
"text": "The discovery of penicillin was a moment of serendipity.",
|
|
148
|
+
"duration": 7,
|
|
149
|
+
"image": {
|
|
150
|
+
"type": "html_tailwind",
|
|
151
|
+
"html": [
|
|
152
|
+
"<div class='h-full flex flex-col justify-center bg-slate-900 px-8'>",
|
|
153
|
+
" <div class='mb-4 p-6 bg-slate-800 rounded-xl border-l-4 border-cyan-400'>",
|
|
154
|
+
" <p class='text-3xl text-white leading-relaxed'>The discovery of penicillin was a moment of <span class='text-cyan-400 font-semibold'>serendipity</span>.</p>",
|
|
155
|
+
" </div>",
|
|
156
|
+
" <div id='tr1' class='p-5 bg-slate-800/50 rounded-xl ml-8' style='opacity:0'>",
|
|
157
|
+
" <p class='text-2xl text-slate-300 leading-relaxed'>ペニシリンの発見はまさに<span class='text-cyan-400 font-semibold'>セレンディピティ</span>の瞬間だった。</p>",
|
|
158
|
+
" </div>",
|
|
159
|
+
"</div>",
|
|
160
|
+
"<script>",
|
|
161
|
+
"function render(frame, totalFrames, fps) {",
|
|
162
|
+
" var tr = document.getElementById('tr1');",
|
|
163
|
+
" tr.style.opacity = interpolate(frame, [120, 135], [0, 1]);",
|
|
164
|
+
" tr.style.transform = 'translateY(' + interpolateWithEasing(frame, [120, 135], [10, 0], Easing.easeOut) + 'px)';",
|
|
165
|
+
"}",
|
|
166
|
+
"</script>"
|
|
167
|
+
],
|
|
168
|
+
"animation": true
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"id": "review_2",
|
|
173
|
+
"speaker": "Presenter",
|
|
174
|
+
"text": "She found the perfect dress by pure serendipity.",
|
|
175
|
+
"duration": 6,
|
|
176
|
+
"image": {
|
|
177
|
+
"type": "html_tailwind",
|
|
178
|
+
"html": [
|
|
179
|
+
"<div class='h-full flex flex-col justify-center bg-slate-900 px-8'>",
|
|
180
|
+
" <div class='mb-4 p-6 bg-slate-800 rounded-xl border-l-4 border-indigo-400'>",
|
|
181
|
+
" <p class='text-3xl text-white leading-relaxed'>She found the perfect dress by pure <span class='text-indigo-400 font-semibold'>serendipity</span>.</p>",
|
|
182
|
+
" </div>",
|
|
183
|
+
" <div id='tr2' class='p-5 bg-slate-800/50 rounded-xl ml-8' style='opacity:0'>",
|
|
184
|
+
" <p class='text-2xl text-slate-300 leading-relaxed'>彼女は全くの<span class='text-indigo-400 font-semibold'>偶然</span>で完璧なドレスを見つけた。</p>",
|
|
185
|
+
" </div>",
|
|
186
|
+
"</div>",
|
|
187
|
+
"<script>",
|
|
188
|
+
"function render(frame, totalFrames, fps) {",
|
|
189
|
+
" var tr = document.getElementById('tr2');",
|
|
190
|
+
" tr.style.opacity = interpolate(frame, [93, 108], [0, 1]);",
|
|
191
|
+
" tr.style.transform = 'translateY(' + interpolateWithEasing(frame, [93, 108], [10, 0], Easing.easeOut) + 'px)';",
|
|
192
|
+
"}",
|
|
193
|
+
"</script>"
|
|
194
|
+
],
|
|
195
|
+
"animation": true
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"id": "review_3",
|
|
200
|
+
"speaker": "Presenter",
|
|
201
|
+
"text": "Serendipity led him to his future business partner at a coffee shop.",
|
|
202
|
+
"duration": 8,
|
|
203
|
+
"image": {
|
|
204
|
+
"type": "html_tailwind",
|
|
205
|
+
"html": [
|
|
206
|
+
"<div class='h-full flex flex-col justify-center bg-slate-900 px-8'>",
|
|
207
|
+
" <div class='mb-4 p-6 bg-slate-800 rounded-xl border-l-4 border-purple-400'>",
|
|
208
|
+
" <p class='text-3xl text-white leading-relaxed'><span class='text-purple-400 font-semibold'>Serendipity</span> led him to his future business partner at a coffee shop.</p>",
|
|
209
|
+
" </div>",
|
|
210
|
+
" <div id='tr3' class='p-5 bg-slate-800/50 rounded-xl ml-8' style='opacity:0'>",
|
|
211
|
+
" <p class='text-2xl text-slate-300 leading-relaxed'><span class='text-purple-400 font-semibold'>セレンディピティ</span>が彼をカフェで未来のビジネスパートナーに導いた。</p>",
|
|
212
|
+
" </div>",
|
|
213
|
+
"</div>",
|
|
214
|
+
"<script>",
|
|
215
|
+
"function render(frame, totalFrames, fps) {",
|
|
216
|
+
" var tr = document.getElementById('tr3');",
|
|
217
|
+
" tr.style.opacity = interpolate(frame, [150, 165], [0, 1]);",
|
|
218
|
+
" tr.style.transform = 'translateY(' + interpolateWithEasing(frame, [150, 165], [10, 0], Easing.easeOut) + 'px)';",
|
|
219
|
+
"}",
|
|
220
|
+
"</script>"
|
|
221
|
+
],
|
|
222
|
+
"animation": true
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
]
|
|
226
|
+
}
|