Skip to content

Commit 5ddad13

Browse files
authored
Merge pull request #8 from diffusionstudio/konstantin/feature/functional-properties
Konstantin/feature/functional properties
2 parents 58dda34 + a3996ab commit 5ddad13

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+876
-260
lines changed

index.html

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,44 @@
11
<!doctype html>
22
<html lang="en">
3-
<head>
4-
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6-
<title>DS Playground</title>
7-
</head>
8-
<body>
9-
<div id="app"></div>
10-
<script type="module" src="playground/main.ts"></script>
11-
</body>
12-
</html>
3+
4+
<head>
5+
<meta charset="UTF-8" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>DS Playground</title>
8+
<link rel="stylesheet" href="/playground/index.css">
9+
</head>
10+
11+
<body>
12+
<div id="app">
13+
<div id="player-container">
14+
<div id="player"></div>
15+
<div id="progress" style="display: none;">
16+
<h1>80%</h1>
17+
</div>
18+
</div>
19+
<div id="timeline">
20+
<div></div>
21+
</div>
22+
<div id="controls">
23+
<div id="playback">
24+
<i data-lucide="skip-back"></i>
25+
<i data-lucide="play"></i>
26+
<i data-lucide="pause" style="display: none;"></i>
27+
<i data-lucide="skip-forward"></i>
28+
</div>
29+
<span id="time">00:00 / 00:00</span>
30+
<i data-lucide="gauge"></i>
31+
<button id="export" type="button">
32+
<div class="loader" style="display: none;"></div>
33+
Export
34+
</button>
35+
</div>
36+
</div>
37+
<script type="module" src="playground/main.ts"></script>
38+
<script src="https://unpkg.com/lucide@latest"></script>
39+
<script>
40+
lucide.createIcons();
41+
</script>
42+
</body>
43+
44+
</html>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@diffusionstudio/core",
33
"private": false,
4-
"version": "1.0.0-rc.1",
4+
"version": "1.0.0-rc.2",
55
"type": "module",
66
"description": "Build bleeding edge video processing applications",
77
"files": [

playground/controls.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import * as core from '../src';
2+
import { exportComposition } from './export';
3+
4+
export function setupControls(composition: core.Composition) {
5+
const handlePlay = () => composition.play();
6+
const handlePause = () => composition.pause();
7+
const handleBack = () => composition.seek(0);
8+
const handleForward = () => composition.seek(composition.duration.frames);
9+
const handleExport = () => exportComposition(composition);
10+
11+
playButton.addEventListener('click', handlePlay);
12+
pauseButton.addEventListener('click', handlePause);
13+
backButton.addEventListener('click', handleBack);
14+
forwardButton.addEventListener('click', handleForward);
15+
exportButton.addEventListener('click', handleExport);
16+
17+
composition.on('play', () => {
18+
playButton.style.display = 'none';
19+
pauseButton.style.display = 'block';
20+
});
21+
composition.on('pause', () => {
22+
pauseButton.style.display = 'none';
23+
playButton.style.display = 'block';
24+
});
25+
composition.on('currentframe', () => {
26+
time.textContent = composition.time();
27+
});
28+
29+
composition.attachPlayer(player);
30+
31+
const observer = new ResizeObserver(() => {
32+
const scale = Math.min(
33+
container.clientWidth / composition.width,
34+
container.clientHeight / composition.height
35+
);
36+
37+
player.style.width = `${composition.width}px`;
38+
player.style.height = `${composition.height}px`;
39+
player.style.transform = `scale(${scale})`;
40+
player.style.transformOrigin = 'center';
41+
});
42+
43+
observer.observe(document.body);
44+
time.textContent = composition.time();
45+
composition.seek(0);
46+
}
47+
48+
const container = document.querySelector('[id="player-container"]') as HTMLDivElement;
49+
const player = document.querySelector('[id="player"]') as HTMLDivElement;
50+
const time = document.querySelector('[id="time"]') as HTMLSpanElement;
51+
const exportButton = document.querySelector('[id="export"]') as HTMLButtonElement;
52+
const playButton = document.querySelector('[data-lucide="play"]') as HTMLElement;
53+
const pauseButton = document.querySelector('[data-lucide="pause"]') as HTMLElement;
54+
const backButton = document.querySelector('[data-lucide="skip-back"]') as HTMLElement;
55+
const forwardButton = document.querySelector('[data-lucide="skip-forward"]') as HTMLElement;

playground/export.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
2+
import * as core from '../src';
3+
4+
let fps = 30;
5+
6+
export async function exportComposition(composition: core.Composition) {
7+
if (loader.style.display != 'none') return;
8+
9+
try {
10+
const encoder = new core.WebcodecsEncoder(composition, { debug: true, fps });
11+
12+
encoder.on('render', (event) => {
13+
const { progress, total } = event.detail;
14+
container.style.display = 'flex';
15+
text.innerHTML = `${Math.round(progress * 100 / total)}%`;
16+
})
17+
18+
const fileHandle = await window.showSaveFilePicker({
19+
suggestedName: `untitled_video.mp4`,
20+
types: [
21+
{
22+
description: 'Video File',
23+
accept: { 'video/mp4': ['.mp4'] },
24+
},
25+
],
26+
});
27+
loader.style.display = 'block';
28+
await encoder.export(fileHandle);
29+
} catch (e) {
30+
if (e instanceof DOMException) {
31+
// user canceled file picker
32+
} else if (e instanceof core.ExportError) {
33+
alert(e.message);
34+
} else {
35+
alert(String(e))
36+
}
37+
} finally {
38+
loader.style.display = 'none';
39+
container.style.display = 'none';
40+
}
41+
}
42+
43+
const container = document.querySelector('[id="progress"]') as HTMLDivElement;
44+
const text = document.querySelector('[id="progress"] > h1') as HTMLHeadingElement;
45+
const loader = document.querySelector('.loader') as HTMLDivElement;
46+
const fpsButton = document.querySelector('[data-lucide="gauge"]') as HTMLElement;
47+
48+
fpsButton.addEventListener('click', () => {
49+
const value = parseFloat(
50+
prompt("Please enter the desired frame rate", fps.toString()) ?? fps.toString()
51+
);
52+
53+
if (!Number.isNaN(value)) fps = value
54+
});

playground/hello-world.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

playground/index.css

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
:root {
2+
--background: 240 10% 3.9%;
3+
--foreground: 0 0% 98%;
4+
--card: 240 10% 3.9%;
5+
--card-foreground: 0 0% 98%;
6+
--popover: 240 10% 3.9%;
7+
--popover-foreground: 0 0% 98%;
8+
--primary: 0 0% 98%;
9+
--primary-foreground: 240 5.9% 10%;
10+
--secondary: 240 3.7% 15.9%;
11+
--secondary-foreground: 0 0% 98%;
12+
--muted: 240 3.7% 15.9%;
13+
--muted-foreground: 240 5% 64.9%;
14+
--accent: 240 3.7% 15.9%;
15+
--accent-foreground: 0 0% 98%;
16+
--destructive: 0 62.8% 30.6%;
17+
--destructive-foreground: 0 0% 98%;
18+
--border: 240 3.7% 15.9%;
19+
--input: 240 3.7% 15.9%;
20+
--ring: 240 4.9% 83.9%;
21+
--chart-1: 220 70% 50%;
22+
--chart-2: 160 60% 45%;
23+
--chart-3: 30 80% 55%;
24+
--chart-4: 280 65% 60%;
25+
--chart-5: 340 75% 55%;
26+
27+
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
28+
line-height: 1.5;
29+
font-weight: 400;
30+
31+
color-scheme: dark;
32+
color: hsl(var(--foreground));
33+
stroke: hsl(var(--foreground));
34+
background-color: hsl(var(--background));
35+
36+
font-synthesis: none;
37+
text-rendering: optimizeLegibility;
38+
-webkit-font-smoothing: antialiased;
39+
-moz-osx-font-smoothing: grayscale;
40+
}
41+
42+
*:focus {
43+
outline: 2px solid hsl(var(--ring));
44+
}
45+
46+
body {
47+
margin: 0;
48+
display: flex;
49+
place-items: center;
50+
min-width: 320px;
51+
min-height: 100vh;
52+
}
53+
54+
[data-lucide] {
55+
cursor: pointer;
56+
}
57+
58+
#app {
59+
max-width: 900px;
60+
margin: 0 auto;
61+
text-align: center;
62+
width: 90vw;
63+
}
64+
65+
button {
66+
border-radius: 6px;
67+
display: flex;
68+
align-items: center;
69+
border: none;
70+
justify-content: center;
71+
gap: 8px;
72+
padding: 0 12px;
73+
height: 34px;
74+
font-size: 14px;
75+
font-weight: 600;
76+
font-family: inherit;
77+
background-color: hsl(var(--foreground));
78+
color: hsl(var(--background));
79+
cursor: pointer;
80+
transition: border-color 0.25s;
81+
}
82+
83+
button:hover {
84+
background: hsl(var(--muted-foreground));
85+
}
86+
87+
#player-container {
88+
aspect-ratio: 16/9;
89+
display: flex;
90+
position: relative;
91+
width: 100%;
92+
margin: 0 auto;
93+
justify-content: center;
94+
border-radius: 6px;
95+
align-items: center;
96+
overflow: hidden;
97+
background-color: rgba(0, 0, 0, 0.3);
98+
overflow: hidden;
99+
}
100+
101+
#progress {
102+
backdrop-filter: blur(40px) brightness(60%);
103+
position: absolute;
104+
inset: 0;
105+
display: flex;
106+
justify-content: center;
107+
align-items: center;
108+
}
109+
110+
#progress>h1 {
111+
font-size: 4rem;
112+
font-weight: 600;
113+
}
114+
115+
#controls {
116+
display: flex;
117+
width: 100%;
118+
justify-content: center;
119+
align-items: center;
120+
gap: 28px;
121+
margin-top: 24px;
122+
margin-bottom: 20px;
123+
}
124+
125+
#playback {
126+
display: flex;
127+
align-items: center;
128+
gap: 15px;
129+
}
130+
131+
#time {
132+
font-weight: 600;
133+
}
134+
135+
.loader {
136+
width: 14px;
137+
padding: 5px;
138+
aspect-ratio: 1;
139+
border-radius: 50%;
140+
background: #000;
141+
--_m:
142+
conic-gradient(#0000 10%, #000),
143+
linear-gradient(#000 0 0) content-box;
144+
-webkit-mask: var(--_m);
145+
mask: var(--_m);
146+
-webkit-mask-composite: source-out;
147+
mask-composite: subtract;
148+
animation: l3 1s infinite linear;
149+
}
150+
151+
152+
@keyframes l3 {
153+
to {
154+
transform: rotate(1turn)
155+
}
156+
}
157+
158+
#timeline {
159+
position: relative;
160+
overflow: hidden;
161+
margin-top: 20px;
162+
width: 100%;
163+
height: 6px;
164+
border-radius: 3px;
165+
background-color: hsl(var(--muted-foreground) / 0.3);
166+
cursor: pointer;
167+
}
168+
169+
#timeline > div {
170+
position: absolute;
171+
left: 0;
172+
width: 4px;
173+
top: 0;
174+
bottom: 0;
175+
background-color: red;
176+
transform: translateX(-2px);
177+
}

0 commit comments

Comments
 (0)