mirror of
https://github.com/PlayEdu/backend
synced 2025-06-19 11:42:49 +08:00
Merge branch 'dev' of https://gitee.com/playeduxyz/backend into dev
This commit is contained in:
commit
d66c19bb4c
@ -12,7 +12,7 @@ import {
|
|||||||
} from "antd";
|
} from "antd";
|
||||||
import Dragger from "antd/es/upload/Dragger";
|
import Dragger from "antd/es/upload/Dragger";
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
import { generateUUID } from "../../utils";
|
import { generateUUID, parseVideo } from "../../utils";
|
||||||
import { minioUploadId } from "../../api/upload";
|
import { minioUploadId } from "../../api/upload";
|
||||||
import { UploadChunk } from "../../js/minio-upload-chunk";
|
import { UploadChunk } from "../../js/minio-upload-chunk";
|
||||||
import { storeResource } from "../../api/resource";
|
import { storeResource } from "../../api/resource";
|
||||||
@ -52,12 +52,13 @@ export const UploadVideoButton = (props: PropsInterface) => {
|
|||||||
multiple: true,
|
multiple: true,
|
||||||
beforeUpload: async (file: File) => {
|
beforeUpload: async (file: File) => {
|
||||||
if (file.type === "video/mp4") {
|
if (file.type === "video/mp4") {
|
||||||
|
let videoInfo = await parseVideo(file);
|
||||||
// 添加到本地待上传
|
// 添加到本地待上传
|
||||||
let data = await getMinioUploadId();
|
let data = await getMinioUploadId();
|
||||||
let run = new UploadChunk(file, data["upload_id"], data["filename"]);
|
let run = new UploadChunk(file, data["upload_id"], data["filename"]);
|
||||||
let item: FileItem = {
|
let item: FileItem = {
|
||||||
id: generateUUID(),
|
id: generateUUID(),
|
||||||
duration: 0,
|
duration: videoInfo.duration,
|
||||||
name: file.name,
|
name: file.name,
|
||||||
size: file.size,
|
size: file.size,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
@ -128,20 +129,6 @@ export const UploadVideoButton = (props: PropsInterface) => {
|
|||||||
上传视频
|
上传视频
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<div className="none">
|
|
||||||
{fileList.length > 0 &&
|
|
||||||
fileList.map((item) => (
|
|
||||||
<video
|
|
||||||
key={item.id}
|
|
||||||
src={URL.createObjectURL(item.file)}
|
|
||||||
onCanPlayThrough={(e: any) => {
|
|
||||||
item.duration = parseInt(e.target.duration);
|
|
||||||
item.loading = false;
|
|
||||||
}}
|
|
||||||
></video>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{showModal && (
|
{showModal && (
|
||||||
<Modal
|
<Modal
|
||||||
width={800}
|
width={800}
|
||||||
|
4
src/types/index.ts
Normal file
4
src/types/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface VideoParseInfo {
|
||||||
|
poster:File;
|
||||||
|
duration:number;
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
|
import { assert } from "console";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
import { VideoParseInfo } from "../types";
|
||||||
|
|
||||||
export function getToken(): string {
|
export function getToken(): string {
|
||||||
return window.localStorage.getItem("playedu-backend-token") || "";
|
return window.localStorage.getItem("playedu-backend-token") || "";
|
||||||
@ -16,7 +18,7 @@ export function dateFormat(dateStr: string) {
|
|||||||
return moment(dateStr).format("YYYY-MM-DD HH:mm");
|
return moment(dateStr).format("YYYY-MM-DD HH:mm");
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateUUID = (): string => {
|
export function generateUUID(): string {
|
||||||
let guid = "";
|
let guid = "";
|
||||||
for (let i = 1; i <= 32; i++) {
|
for (let i = 1; i <= 32; i++) {
|
||||||
let n = Math.floor(Math.random() * 16.0).toString(16);
|
let n = Math.floor(Math.random() * 16.0).toString(16);
|
||||||
@ -24,4 +26,56 @@ export const generateUUID = (): string => {
|
|||||||
if (i === 8 || i === 12 || i === 16 || i === 20) guid += "-";
|
if (i === 8 || i === 12 || i === 16 || i === 20) guid += "-";
|
||||||
}
|
}
|
||||||
return guid;
|
return guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function transformBase64ToBlob(
|
||||||
|
base64: string,
|
||||||
|
mime: string,
|
||||||
|
filename: string
|
||||||
|
): File {
|
||||||
|
const arr = base64.split(",");
|
||||||
|
const bstr = atob(arr[1]);
|
||||||
|
let n = bstr.length;
|
||||||
|
const u8arr = new Uint8Array(n);
|
||||||
|
while (n--) {
|
||||||
|
u8arr[n] = bstr.charCodeAt(n);
|
||||||
|
}
|
||||||
|
return new File([u8arr], filename, { type: mime });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseVideo(file: File): Promise<VideoParseInfo> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let video = document.createElement("video");
|
||||||
|
video.muted = true;
|
||||||
|
video.setAttribute("src", URL.createObjectURL(file));
|
||||||
|
video.setAttribute("autoplay", "autoplay");
|
||||||
|
video.setAttribute("crossOrigin", "anonymous"); //设置跨域 否则toDataURL导出图片失败
|
||||||
|
video.setAttribute("width", "400"); //设置大小,如果不设置,下面的canvas就要按需设置
|
||||||
|
video.setAttribute("height", "300");
|
||||||
|
video.currentTime = 7; //视频时长,一定要设置,不然大概率白屏
|
||||||
|
video.addEventListener("loadeddata", function () {
|
||||||
|
let canvas = document.createElement("canvas"),
|
||||||
|
width = video.width, //canvas的尺寸和图片一样
|
||||||
|
height = video.height;
|
||||||
|
canvas.width = width; //画布大小,默认为视频宽高
|
||||||
|
canvas.height = height;
|
||||||
|
let ctx = canvas.getContext("2d");
|
||||||
|
if (!ctx) {
|
||||||
|
return reject("无法捕获视频帧");
|
||||||
|
}
|
||||||
|
ctx.drawImage(video, 0, 0, width, height); //绘制canvas
|
||||||
|
let dataURL = canvas.toDataURL("image/png"); //转换为base64
|
||||||
|
const imageFile = transformBase64ToBlob(
|
||||||
|
dataURL,
|
||||||
|
"image/png",
|
||||||
|
file.name + ".png"
|
||||||
|
);
|
||||||
|
video.remove();
|
||||||
|
let info: VideoParseInfo = {
|
||||||
|
poster: imageFile,
|
||||||
|
duration: parseInt(video.duration + ""),
|
||||||
};
|
};
|
||||||
|
return resolve(info);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user