recorder.ondataavailable = (event) => {
videoFile = URL.createObjectURL(event.data);
// blob:http://localhost:4000/938d5a5f-4b94-4bf8-ae62-75f4cb083194
// >> 브라우저 메모리상에 존재하는 url > 이걸로 파일에 접근가능
import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";
const handleDownload = async () => {
const ffmpeg = createFFmpeg({log: true});
await ffmpeg.load();
//FS = file system
ffmpeg.FS("writeFile", "recording.webm", await fetchFile(videoFile));
// ffmpeg.run(input, input,..,"초당프레임수" output)
await ffmpeg.run("-i", "recording.webm","-r", "60", "output.mp4");
const handleDownload = async () => {
...
const mp4File = ffmpeg.FS("readFile", "output.mp4"); // >> array 형태임
//create blob from array << arrayBuffer로 만들어야함
const mp4Blob = new Blob([mp4File.buffer], { type: "video/mp4" });
const mp4Url = URL.createObjectURL(mp4Blob);
const a = document.createElement("a");
a.href = mp4Url;
a.download = "MyRecording.mp4";
document.body.appendChild(a);
a.click();
startBtn.innerText = "Start Recording";
};
[server.js]
app.use((req, res, next) => {
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
next();
});
=================
[header.pug]
...
else
img.header__avatar(src="/" + loggedInUser.avatarUrl, crossorigin)
const handleDownload = async () => {
const ffmpeg = createFFmpeg({ log: true });
await ffmpeg.load();
...
// ss>> 영상의 특정시간대로 가게해줌, -frames:v>> 이동한시간의 스샷n장 찍음
await ffmpeg.run(
"-i",
"recording.webm",
"-ss",
"00:00:01",
"-frames:v",
"1",
"thumbnail.jpg"
);
const thumbFile = ffmpeg.FS("readFile", "thumbnail.jpg");
//create blob from array << arrayBuffer로 만들어야함
const thumbBlob = new Blob([thumbFile.buffer], { type: "image/jpg" });
const thumbUrl = URL.createObjectURL(thumbBlob);
const thumbA = document.createElement("a");
thumbA.href = thumbUrl;
thumbA.download = "MyThumbnail.jpg";
document.body.appendChild(thumbA);
thumbA.click();
...
};
const handleDownload = async () => {
ffmpeg.FS("unlink", "recording.webm");
ffmpeg.FS("unlink", "output.mp4");
ffmpeg.FS("unlink", "thumbnail.jpg");
URL.revokeObjectURL(mp4Url);
URL.revokeObjectURL(thumbUrl);
URL.revokeObjectURL(videoFile);
}
[video.js]
const videoSchema = new mongoose.Schema({
...
thumbUrl: { type: String, required: true },
===========================
[upload.pug]
form(method="POST", enctype="multipart/form-data")
label(for="video") Video File
input(type="file", accept="video/*", required, id="video", name="video")
label(for="thumb") Thumbnail File
input(type="file", accept="image/*", required, id="thumb", name="thumb")
===========================
[videoRouter.js]
videoRouter
.route("/upload")
.all(protectorMiddleware)
.get(getUpload)
.post(videoUpload.single("video"), postUpload);
>>
videoRouter
.route("/upload")
.all(protectorMiddleware)
.get(getUpload)
.post(
videoUpload.fields([
{ name: "video", maxCount: 1 },
{ name: "thumb", maxCount: 1 },
]),
postUpload
);
[videoContorller.js]
export const postUpload = async (req, res) => {
..
const { video, thumb } = req.files;
..
try {
const newVideo = await Video.create({
..
fileUrl: video[0].path,
thumbUrl: thumb[0].path,
..
});
..
};
[Video.js]
videoSchema.static("changePathFormula", (urlPath) => {
return urlPath.replace(/\\/g, "/");
});
----------------------
[videoController.js]
export const postUpload = async (req, res) => {
...
thumbUrl: Video.changePathFormula(thumb[0].path),
ch16. comment section (0) | 2022.09.05 |
---|---|
ch15. flash message (0) | 2022.09.05 |
ch13. video recorder (0) | 2022.09.01 |
ch12. Views api << 템플릿 렌더링 X (0) | 2022.09.01 |
ch11.6~ video play (2) (0) | 2022.08.31 |
댓글 영역