├── .gitignore
├── src
├── assets
│ └── favicon.ico
├── index.jsx
├── hooks
│ └── useFFmpeg.jsx
└── App.jsx
├── index.html
├── vite.config.js
├── package.json
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
--------------------------------------------------------------------------------
/src/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harshmangalam/ffmpeg-solidjs/HEAD/src/assets/favicon.ico
--------------------------------------------------------------------------------
/src/index.jsx:
--------------------------------------------------------------------------------
1 | /* @refresh reload */
2 | import { render } from 'solid-js/web';
3 |
4 | import App from './App';
5 |
6 | render(() => , document.getElementById('root'));
7 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Solid App
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import solidPlugin from "vite-plugin-solid";
3 |
4 | export default defineConfig({
5 | plugins: [
6 | solidPlugin(),
7 | {
8 | name: "configure-response-headers",
9 | configureServer: (server) => {
10 | server.middlewares.use((_req, res, next) => {
11 | res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
12 | res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
13 | next();
14 | });
15 | },
16 | },
17 | ],
18 | build: {
19 | target: "esnext",
20 | polyfillDynamicImport: false,
21 | },
22 | });
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vite-template-solid",
3 | "version": "0.0.0",
4 | "description": "",
5 | "scripts": {
6 | "start": "vite",
7 | "dev": "vite",
8 | "build": "vite build",
9 | "serve": "vite preview"
10 | },
11 | "license": "MIT",
12 | "devDependencies": {
13 | "vite": "^2.8.6",
14 | "vite-plugin-cross-origin-isolation": "^0.1.6",
15 | "vite-plugin-solid": "^2.2.6"
16 | },
17 | "dependencies": {
18 | "@ffmpeg/core": "^0.10.0",
19 | "@ffmpeg/ffmpeg": "^0.10.1",
20 | "@hope-ui/solid": "^0.5.0",
21 | "@stitches/core": "^1.2.8",
22 | "solid-js": "^1.3.13",
23 | "solid-transition-group": "^0.0.10"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/hooks/useFFmpeg.jsx:
--------------------------------------------------------------------------------
1 | import { createStore } from "solid-js/store";
2 | import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";
3 |
4 | export default function useFFmpeg() {
5 | const [store, setStore] = createStore({
6 | progress: null,
7 | videoURL: null,
8 | });
9 |
10 | const ffmpeg = createFFmpeg({ progress: (e) => setStore("progress", e) });
11 |
12 | const transcode = async (file) => {
13 | const { name } = file;
14 | await ffmpeg.load();
15 | ffmpeg.FS("writeFile", name, await fetchFile(file));
16 | await ffmpeg.run("-i", name, "output.mp4");
17 | const data = ffmpeg.FS("readFile", "output.mp4");
18 | const url = URL.createObjectURL(
19 | new Blob([data.buffer], { type: "video/mp4" })
20 | );
21 |
22 | setStore("videoURL", url);
23 | setStore("progress", null);
24 | };
25 |
26 | const handleFileChange = (e) => {
27 | transcode(e.target.files[0]);
28 | };
29 | return {
30 | store,
31 | handleFileChange,
32 | };
33 | }
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Usage
2 |
3 | Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`.
4 |
5 | This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely be removed once you clone a template.
6 |
7 | ```bash
8 | $ npm install # or pnpm install or yarn install
9 | ```
10 |
11 | ### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)
12 |
13 | ## Available Scripts
14 |
15 | In the project directory, you can run:
16 |
17 | ### `npm dev` or `npm start`
18 |
19 | Runs the app in the development mode.
20 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
21 |
22 | The page will reload if you make edits.
23 |
24 | ### `npm run build`
25 |
26 | Builds the app for production to the `dist` folder.
27 | It correctly bundles Solid in production mode and optimizes the build for the best performance.
28 |
29 | The build is minified and the filenames include the hashes.
30 | Your app is ready to be deployed!
31 |
32 | ## Deployment
33 |
34 | You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.)
35 |
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | Box,
3 | Button,
4 | CircularProgress,
5 | CircularProgressIndicator,
6 | CircularProgressLabel,
7 | Container,
8 | Flex,
9 | Heading,
10 | HopeProvider,
11 | HStack,
12 | Text,
13 | VStack,
14 | } from "@hope-ui/solid";
15 | import useFFmpeg from "./hooks/useFFmpeg";
16 | import { Show } from "solid-js";
17 | function App() {
18 | let fileRef;
19 | const { store, handleFileChange } = useFFmpeg();
20 | return (
21 |
22 |
23 |
24 |
25 | Video processing in browser using
26 |
27 |
28 | FFmpeg{" "}
29 |
30 | and{" "}
31 |
32 | SolidJS
33 |
34 |
35 |
36 |
37 |
38 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
56 |
57 |
58 |
59 | Ratio
60 |
61 | {Math.round(store.progress?.ratio * 100)} %
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | Duration
72 |
73 | {store.progress?.duration}
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | Time
84 | {store.progress?.time}
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
100 |
101 |
102 |
103 |
104 | );
105 | }
106 |
107 | export default App;
108 |
--------------------------------------------------------------------------------