1 | <script lang="ts"> |
2 | import PageContainer from "$lib/components/PageContainer.svelte"; |
3 | import "highlight.js/styles/github-dark.css"; |
4 | import { onMount } from "svelte"; |
5 | import { Highlight, HighlightSvelte, LineNumbers } from "svelte-highlight"; |
6 | import { cpp, javascript, json } from "svelte-highlight/languages/index.js"; |
7 |
|
8 | export let data; |
9 |
|
10 | let loaded = false; |
11 | let worker: Worker; |
12 | let stdout: string = "[JS] Loading FFmpeg..."; |
13 | let processResponse: string = ''; |
14 |
|
15 | onMount(() => { |
16 | worker = new Worker("./ffmpeg-wasm/worker.js", { |
17 | name: "worker.js", |
18 | }); |
19 |
|
20 | worker.addEventListener("message", (msg) => { |
21 | if (msg.data.type === "stdout") { |
22 | stdout += msg.data.payload; |
23 | } |
24 | if (msg.data.type === "loaded") { |
25 | loaded = msg.data.payload; |
26 | } |
27 | if (msg.data.type === "processResponse") { |
28 | processResponse = msg.data.payload |
29 | } |
30 | }); |
31 | }); |
32 |
|
33 | async function process(e: Event) { |
34 | e.preventDefault(); |
35 | const fileInput = document.getElementById('inputFile') as HTMLInputElement; |
36 | if (!fileInput.files) return; |
37 | stdout += "[JS] Sending file from JS to WASM\n"; |
38 | const file = fileInput.files[0]; |
39 | if (!file) { |
40 | console.log("No file selected"); |
41 | return; |
42 | } |
43 |
|
44 | worker.postMessage({ |
45 | type: "process", |
46 | payload: { name: file.name, data: file } |
47 | }) |
48 | } |
49 | </script> |
50 |
|
51 | <svelte:head> |
52 | <style> |
53 | #stdout { |
54 | background-color: black; |
55 | color: green; |
56 | min-height: 200px; |
57 | padding: 10px; |
58 | font-weight: bold; |
59 | font-family: monospace; |
60 | white-space: pre-wrap; |
61 | } |
62 | #file-form { |
63 | display: flex; |
64 | flex-shrink: 1; |
65 | flex-direction: column; |
66 | gap: 10px; |
67 | } |
68 | </style> |
69 | </svelte:head> |
70 |
|
71 | <PageContainer> |
72 | <div> |
73 | <div class="text-2xl font-bold text-secondary"> |
74 | {data.title} |
75 | </div> |
76 | <div class="text-sm font-bold text-primary"> |
77 | Written: {data.written} |
78 | </div> |
79 |
|
80 | <div> |
81 | This is a WASM example on FFmpeg, compiled from source. |
82 | </div> |
83 |
|
84 | <form id="file-form" on:submit={process}> |
85 | <h6 class="text">Select a media file from your device (nothing is uploaded to a server, it's all processed on your machine 😃)</h6> |
86 | |
87 | <input id="inputFile" type="file" /> |
88 | <button |
89 | disabled={!loaded} |
90 | class="btn btn-primary" |
91 | type="submit" |
92 | > |
93 | Get streams metadata |
94 | </button> |
95 | <div id="stdout">{stdout}</div> |
96 | </form> |
97 |
|
98 | <div class="flex flex-col gap-2 mt-5"> |
99 | Result: |
100 | <Highlight language={json} code={processResponse} let:highlighted> |
101 | <LineNumbers {highlighted} /> |
102 | </Highlight> |
103 |
|
104 | <h1 class="text-primary text-2xl">Source code</h1> |
105 |
|
106 | 1. main.cpp |
107 | <Highlight language={cpp} code={data["main.cpp"]} let:highlighted> |
108 | <LineNumbers {highlighted} /> |
109 | </Highlight> |
110 |
|
111 | 2. page.svelte (this page) |
112 | <HighlightSvelte code={data["svelteSource"]} let:highlighted> |
113 | <LineNumbers {highlighted} /> |
114 | </HighlightSvelte> |
115 |
|
116 | 3. worker.js |
117 | <Highlight language={javascript} code={data.workerSource} let:highlighted> |
118 | <LineNumbers {highlighted} /> |
119 | </Highlight > |
120 |
|
121 | 4. FFmpeg build script using emscripten |
122 | <Highlight language={javascript} code={data.ffmpegBuild} let:highlighted> |
123 | <LineNumbers {highlighted} /> |
124 | </Highlight > |
125 |
|
126 | 5. WASM build script |
127 | <Highlight language={javascript} code={data.wasmBuild} let:highlighted> |
128 | <LineNumbers {highlighted} /> |
129 | </Highlight > |
130 | </div> |
131 |
|
132 | References: |
133 | <ul class="list-disc p-[revert] pb-2"> |
134 | <li class="list-item"><a class="link-secondary" href="https://jeromewu.github.io/build-ffmpeg-webassembly-version-part-2-compile-with-emscripten">https://jeromewu.github.io/build-ffmpeg-webassembly-version-part-2-compile-with-emscripten</a></li> |
135 | <li><a class="link-secondary" href="https://github.com/ffmpegwasm/ffmpeg.wasm">https://github.com/ffmpegwasm/ffmpeg.wasm</a></li> |
136 | <li><a class="link-secondary" href="https://github.com/sc0ty/subsync">https://github.com/sc0ty/subsync</a></li> |
137 | </ul> |
138 | </div> |
139 | </PageContainer> |
140 |
|