Skip to content

Commit 364da30

Browse files
committed
Upgrade nextjs version and fix example
1 parent 5c1e224 commit 364da30

File tree

5 files changed

+279
-310
lines changed

5 files changed

+279
-310
lines changed

apps/nextjs-app/app/Home.tsx

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
'use client'
2+
3+
import { FFmpeg } from '@ffmpeg/ffmpeg'
4+
import { fetchFile, toBlobURL } from '@ffmpeg/util'
5+
import { useRef, useState } from 'react'
6+
7+
export default function Home() {
8+
const [loaded, setLoaded] = useState(false)
9+
const [isLoading, setIsLoading] = useState(false)
10+
const ffmpegRef = useRef(new FFmpeg())
11+
const videoRef = useRef<HTMLVideoElement | null>(null)
12+
const messageRef = useRef<HTMLParagraphElement | null>(null)
13+
14+
const load = async () => {
15+
setIsLoading(true)
16+
const baseURL = 'https://unpkg.com/@ffmpeg/[email protected]/dist/umd'
17+
const ffmpeg = ffmpegRef.current
18+
ffmpeg.on('log', ({ message }) => {
19+
if (messageRef.current) messageRef.current.innerHTML = message
20+
})
21+
// toBlobURL is used to bypass CORS issue, urls with the same
22+
// domain can be used directly.
23+
await ffmpeg.load({
24+
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
25+
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm')
26+
})
27+
setLoaded(true)
28+
setIsLoading(false)
29+
}
30+
31+
const transcode = async () => {
32+
const ffmpeg = ffmpegRef.current
33+
// u can use 'https://ffmpegwasm.netlify.app/video/video-15s.avi' to download the video to public folder for testing
34+
await ffmpeg.writeFile('input.avi', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi'))
35+
await ffmpeg.exec(['-i', 'input.avi', 'output.mp4'])
36+
const data = (await ffmpeg.readFile('output.mp4')) as any
37+
if (videoRef.current)
38+
videoRef.current.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }))
39+
}
40+
41+
return loaded ? (
42+
<div className="fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]">
43+
<video ref={videoRef} controls></video>
44+
<br />
45+
<button
46+
onClick={transcode}
47+
className="bg-green-500 hover:bg-green-700 text-white py-3 px-6 rounded"
48+
>
49+
Transcode avi to mp4
50+
</button>
51+
<p ref={messageRef}></p>
52+
</div>
53+
) : (
54+
<button
55+
className="fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] flex items-center bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded"
56+
onClick={load}
57+
>
58+
Load ffmpeg-core
59+
{isLoading && (
60+
<span className="animate-spin ml-3">
61+
<svg
62+
viewBox="0 0 1024 1024"
63+
focusable="false"
64+
data-icon="loading"
65+
width="1em"
66+
height="1em"
67+
fill="currentColor"
68+
aria-hidden="true"
69+
>
70+
<path d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"></path>
71+
</svg>
72+
</span>
73+
)}
74+
</button>
75+
)
76+
}

apps/nextjs-app/app/NoSSRWrapper.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import dynamic from 'next/dynamic'
2+
import React from 'react'
3+
const NoSSRWrapper = props => (
4+
<React.Fragment>{props.children}</React.Fragment>
5+
)
6+
export default dynamic(() => Promise.resolve(NoSSRWrapper), {
7+
ssr: false
8+
})

apps/nextjs-app/app/page.tsx

Lines changed: 4 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,8 @@
11
'use client'
22

3-
import { FFmpeg } from '@ffmpeg/ffmpeg'
4-
import { fetchFile, toBlobURL } from '@ffmpeg/util'
5-
import { useRef, useState } from 'react'
3+
import NoSSRWrapper from "./NoSSRWrapper";
4+
import Home from "./Home";
65

7-
export default function Home() {
8-
const [loaded, setLoaded] = useState(false)
9-
const [isLoading, setIsLoading] = useState(false)
10-
const ffmpegRef = useRef(new FFmpeg())
11-
const videoRef = useRef<HTMLVideoElement | null>(null)
12-
const messageRef = useRef<HTMLParagraphElement | null>(null)
13-
14-
const load = async () => {
15-
setIsLoading(true)
16-
const baseURL = 'https://unpkg.com/@ffmpeg/[email protected]/dist/umd'
17-
const ffmpeg = ffmpegRef.current
18-
ffmpeg.on('log', ({ message }) => {
19-
if (messageRef.current) messageRef.current.innerHTML = message
20-
})
21-
// toBlobURL is used to bypass CORS issue, urls with the same
22-
// domain can be used directly.
23-
await ffmpeg.load({
24-
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
25-
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm')
26-
})
27-
setLoaded(true)
28-
setIsLoading(false)
29-
}
30-
31-
const transcode = async () => {
32-
const ffmpeg = ffmpegRef.current
33-
// u can use 'https://ffmpegwasm.netlify.app/video/video-15s.avi' to download the video to public folder for testing
34-
await ffmpeg.writeFile('input.avi', await fetchFile('video-15s.avi'))
35-
await ffmpeg.exec(['-i', 'input.avi', 'output.mp4'])
36-
const data = (await ffmpeg.readFile('output.mp4')) as any
37-
if (videoRef.current)
38-
videoRef.current.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }))
39-
}
40-
41-
return loaded ? (
42-
<div className="fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]">
43-
<video ref={videoRef} controls></video>
44-
<br />
45-
<button
46-
onClick={transcode}
47-
className="bg-green-500 hover:bg-green-700 text-white py-3 px-6 rounded"
48-
>
49-
Transcode avi to mp4
50-
</button>
51-
<p ref={messageRef}></p>
52-
</div>
53-
) : (
54-
<button
55-
className="fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] flex items-center bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded"
56-
onClick={load}
57-
>
58-
Load ffmpeg-core
59-
{isLoading && (
60-
<span className="animate-spin ml-3">
61-
<svg
62-
viewBox="0 0 1024 1024"
63-
focusable="false"
64-
data-icon="loading"
65-
width="1em"
66-
height="1em"
67-
fill="currentColor"
68-
aria-hidden="true"
69-
>
70-
<path d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"></path>
71-
</svg>
72-
</span>
73-
)}
74-
</button>
75-
)
6+
export default function Page() {
7+
return <NoSSRWrapper><Home /></NoSSRWrapper>
768
}

apps/nextjs-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"autoprefixer": "10.4.14",
1818
"eslint": "8.46.0",
1919
"eslint-config-next": "13.4.13",
20-
"next": "13.5.0",
20+
"next": "^14.0.4",
2121
"postcss": "8.4.31",
2222
"react": "18.2.0",
2323
"react-dom": "18.2.0",

0 commit comments

Comments
 (0)