├── .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 | 101 | 102 | 103 | 104 | ); 105 | } 106 | 107 | export default App; 108 | --------------------------------------------------------------------------------