video-flow-b/utils/tools.ts
2025-10-14 18:43:10 +08:00

120 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ScriptSlice, ScriptSliceType } from "@/app/service/domain/valueObject";
export function parseScriptEntity(text: string): ScriptSlice {
const scriptSlice = new ScriptSlice(
// 生成唯一ID单次使用即可
`${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`,
ScriptSliceType.text,
text,
{}
);
return scriptSlice;
}
/**
* @description 节流函数,限制函数在指定时间间隔内只执行一次
* @param {Function} func - 需要被节流的函数
* @param {number} delay - 节流时间间隔(毫秒)
* @returns {Function} - 节流后的新函数
* @throws {Error} - 如果参数类型不正确
* @example
* const throttledFn = throttle(() => { console.log('触发'); }, 1000);
* window.addEventListener('resize', throttledFn);
*/
export function throttle<T extends (...args: any[]) => any>(
func: T,
delay: number = 100
): (...args: Parameters<T>) => void {
if (typeof delay !== "number" || delay < 0) {
throw new Error("throttle: 第二个参数必须是非负数");
}
let lastCall = 0;
return (...args: Parameters<T>) => {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
func(...args);
}
};
}
/**
* 创建1920x1080屏幕适配的CSS样式
* 自动计算缩放比例并应用到页面元素
*/
export function createScreenAdapter(): void {
// 获取当前窗口尺寸
const currentWidth = window.innerWidth;
const currentHeight = window.innerHeight;
// 计算缩放比例 (1920x1080)
const wScale = currentWidth / 1920;
const hScale = currentHeight / 1080;
// 检查app节点是否存在
const app = document.getElementById("app");
if (!app) {
console.error("未找到app节点");
return;
}
(window as any).Scale = {
wScale,
hScale,
};
// 创建样式元素
const style = document.createElement("style");
// 设置CSS样式
style.textContent = `
body {
#app {
transform-origin: top left;
transform: scale(${wScale}, ${hScale});
width: 1920px;
height: 1080px;
}
}
`;
// 将样式添加到head
document.head.appendChild(style);
}
export const downloadVideo = async (url: string) => {
try {
const modifyUrl = decodeURIComponent(url);
const response = await fetch(modifyUrl);
const blob = await response.blob();
const blobUrl = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = blobUrl;
a.download = modifyUrl.split('/').pop() || 'video.mp4';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(blobUrl);
} catch (error) {
console.error('下载视频失败:', error);
}
};
/**
* 下载所有视频
* @param urls 视频URL列表
*/
export const downloadAllVideos = async (urls: string[]) => {
for (const url of urls) {
await downloadVideo(url);
}
};
/**
* 阿里云地址 七牛云地址 取首帧方式不一样
* 发现 链接 包含 aliyuncs.com 是阿里云地址
* @param url 视频URL
*/
export const getFirstFrame = (url: string, width?: number) => {
if (url.includes('aliyuncs.com')) {
return url + '?x-oss-process=video/snapshot,t_1000,f_jpg' + `${width ? ',w_'+width : ''}`;
} else {
return url + '?vframe/jpg/offset/1' + `${width ? '/w/'+width : ''}`;
}
}