Merge pull request #716 from toshihikoyanase/add-wavesurfer

Use WaveSurfer instead of `audio` tag.
This commit is contained in:
keisuke umezawa
2023-12-13 18:21:03 +09:00
committed by GitHub
4 changed files with 93 additions and 5 deletions
@@ -3,6 +3,7 @@ import {
ThreejsArtifactViewer,
isThreejsArtifact,
} from "./ThreejsArtifactViewer"
import { WaveSurferArtifactViewer } from "./WaveSurferArtifactViewer"
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile"
import { CardMedia, Box } from "@mui/material"
@@ -43,9 +44,12 @@ export const ArtifactCardMedia: FC<{
alignItems: "center",
}}
>
<audio controls style={{ width: "100%" }}>
<source src={urlPath} type={artifact.mimetype} />
</audio>
<WaveSurferArtifactViewer
height={100}
waveColor="rgb(200, 0, 200)"
progressColor="rgb(100, 0, 100)"
url={urlPath}
/>
</Box>
)
} else if (artifact.mimetype.startsWith("image")) {
@@ -0,0 +1,72 @@
import React, { useCallback, useEffect, useState, useRef } from "react"
import WaveSurfer from "wavesurfer.js"
import { Box } from "@mui/material"
interface WaveSurferArtifactViewerProps {
height: number
waveColor: string
progressColor: string
url: string
}
const useWavesurfer = (
containerRef: React.MutableRefObject<HTMLDivElement>,
options: WaveSurferArtifactViewerProps
) => {
const [wavesurfer, setWavesurfer] = useState<WaveSurfer | null>(null)
useEffect(() => {
if (!containerRef.current) return
const ws = WaveSurfer.create({
...options,
container: containerRef.current,
})
setWavesurfer(ws)
return () => {
ws.destroy()
}
}, [containerRef])
return wavesurfer
}
// Create a React component of wavesurfer.
export const WaveSurferArtifactViewer: React.FC<
WaveSurferArtifactViewerProps
> = (props) => {
const containerRef = useRef<HTMLDivElement>(null!)
const [isPlaying, setIsPlaying] = useState(false)
const wavesurfer = useWavesurfer(containerRef, props)
const onPlayClick = useCallback(() => {
if (!wavesurfer) return
wavesurfer.isPlaying() ? wavesurfer.pause() : wavesurfer.play()
}, [wavesurfer])
useEffect(() => {
if (!wavesurfer) return
setIsPlaying(false)
const subscriptions = [
wavesurfer.on("play", () => setIsPlaying(true)),
wavesurfer.on("pause", () => setIsPlaying(false)),
]
return () => {
subscriptions.forEach((unsub) => unsub())
}
}, [wavesurfer])
return (
<Box style={{ width: "100%", display: "flex", flexDirection: "column" }}>
<div ref={containerRef} style={{ minHeight: "120px", width: "100%" }} />
<button onClick={onPlayClick} style={{ marginTop: "1em" }}>
{isPlaying ? "Pause" : "Play"}
</button>
</Box>
)
}
+12 -1
View File
@@ -32,7 +32,8 @@
"rehype-raw": "^6.1.1",
"remark-gfm": "^3.0.1",
"remark-math": "^5.1.1",
"three": "^0.155.0"
"three": "^0.155.0",
"wavesurfer.js": "^7.4.12"
},
"devDependencies": {
"@babel/core": "^7.14.3",
@@ -14824,6 +14825,11 @@
"node": ">=10.13.0"
}
},
"node_modules/wavesurfer.js": {
"version": "7.4.12",
"resolved": "https://registry.npmjs.org/wavesurfer.js/-/wavesurfer.js-7.4.12.tgz",
"integrity": "sha512-KzH4LkcOp8LECs9cOVIPBl6vsSoICKuZz+v5kh/zvxilpaVszU+QKC+4s2KEAqcCxBCecg3cNSg4RqAx278F8g=="
},
"node_modules/web-namespaces": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
@@ -25938,6 +25944,11 @@
"graceful-fs": "^4.1.2"
}
},
"wavesurfer.js": {
"version": "7.4.12",
"resolved": "https://registry.npmjs.org/wavesurfer.js/-/wavesurfer.js-7.4.12.tgz",
"integrity": "sha512-KzH4LkcOp8LECs9cOVIPBl6vsSoICKuZz+v5kh/zvxilpaVszU+QKC+4s2KEAqcCxBCecg3cNSg4RqAx278F8g=="
},
"web-namespaces": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
+2 -1
View File
@@ -41,7 +41,8 @@
"rehype-raw": "^6.1.1",
"remark-gfm": "^3.0.1",
"remark-math": "^5.1.1",
"three": "^0.155.0"
"three": "^0.155.0",
"wavesurfer.js": "^7.4.12"
},
"devDependencies": {
"@babel/core": "^7.14.3",