彩云小梦如何控制 AI续写的情感细腻度与悲喜反差?
2026-07-31
2026-08-05 0

开发视频上传功能时,一个常见问题是:用户选择视频后,应该先在客户端压缩,还是直接上传原文件,再由服务器统一转码?
这三种方案都能完成视频处理,但适用场景、开发成本和用户体验差别很大。选错方案可能导致上传时间过长、服务器负载升高,甚至让真正需要保留的高清素材遭到不可逆压缩。
本文从实际项目角度,对三种常见方案进行拆解。
最简单的做法,是在上传页面明确文件限制。当视频超过限制时,提示用户先生成一个较小的分享版本。
基本流程如下:
选择视频 ↓检查文件大小 ↓超过限制 ↓用户压缩视频 ↓重新选择并上传前端可以先读取文件大小:
const input = document.getElementById("videoInput");const message = document.getElementById("message");const MAX_SIZE = 100 * 1024 * 1024;input.addEventListener("change", (event) => { const file = event.target.files[0]; if (!file) return; const sizeMB = file.size / 1024 / 1024; if (file.size > MAX_SIZE) { message.textContent = `当前文件为 ${sizeMB.toFixed(1)} MB,` + "超过100 MB上传限制,请压缩后重试。"; return; } message.textContent = "文件大小符合要求,可以上传。";});如果系统本身没有客户端转码能力,可以让用户借助 Video Compressor 生成体积更小的副本,然后重新上传。
这种方案适合:
它的优点是开发成本低,能够在上传前直接减少流量消耗。缺点是处理步骤转移给了用户,压缩参数也不容易统一。
如果业务需要保留原始视频,前端可以申请预签名地址,将文件直接上传到对象存储,不经过应用服务器。
典型流程为:
浏览器 ↓ 请求上传凭证业务服务器 ↓ 返回预签名地址浏览器 ↓ 直传文件对象存储 ↓ 上传完成通知业务服务器前端示例:
async function uploadToStorage(file) { const ticketResponse = await fetch("/api/upload-ticket", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ fileName: file.name, fileSize: file.size, fileType: file.type }) }); if (!ticketResponse.ok) { throw new Error("无法获取上传凭证"); } const { uploadUrl, fileId } = await ticketResponse.json(); const uploadResponse = await fetch(uploadUrl, { method: "PUT", headers: { "Content-Type": file.type }, body: file }); if (!uploadResponse.ok) { throw new Error("视频上传失败"); } return fileId;}这种方式可以降低应用服务器的带宽和连接压力,也适合后续使用消息队列触发转码任务。
比较适合:
但对象存储直传不等于可以完全信任客户端。服务端仍然需要验证文件大小、扩展名、媒体类型、上传状态和访问权限。
预签名地址也应设置较短的有效期,并限制上传路径与文件大小。
服务端转码的核心优势是参数统一。
无论用户上传MOV、MP4还是其他格式,系统都可以生成统一的视频版本,例如:
源文件├── 1080p播放版本├── 720p移动端版本├── 预览片段└── 封面图片FFmpeg示例:
ffmpeg -i input.mov -vf "scale=-2:1080" -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k -movflags +faststart output-1080p.mp4不建议在HTTP请求中同步执行转码,因为视频处理可能持续数分钟,容易造成请求超时。
更合理的架构是:
上传完成 ↓写入转码任务 ↓消息队列 ↓转码节点处理 ↓保存输出文件 ↓更新任务状态业务表可以记录:
uploadedqueuedprocessingcompletedfailed前端通过轮询或WebSocket获取处理状态。
| 方案 | 优点 | 局限 | 适合场景 |
|---|---|---|---|
| 用户上传前压缩 | 开发简单,节省上传流量 | 参数不统一,增加用户操作 | 工单、录屏、临时分享 |
| 原文件直传 | 保留源文件,应用服务器压力小 | 上传时间长,存储成本高 | 素材库、课程、内容平台 |
| 服务端统一转码 | 输出标准统一,可生成多个版本 | 需要计算资源和任务调度 | 正式视频产品、长期运营平台 |
实际项目也可以组合使用。
例如,普通附件超过100MB时要求用户先压缩;专业素材则允许原文件直传对象存储,上传后再由服务端异步转码。
同样是100MB,可能是一分钟的高码率视频,也可能是十分钟的普通录屏。
上传前还可以读取:
根据业务设置更具体的规则:
function validateVideo(file, metadata) { const errors = []; if (file.size > 100 * 1024 * 1024) { errors.push("文件超过100 MB"); } if (metadata.duration > 600) { errors.push("视频时长不能超过10分钟"); } if (metadata.width > 3840) { errors.push("暂不接受宽度超过3840的视频"); } return errors;}前端校验主要用于改善体验,真正的安全校验仍应放在服务端完成。
视频文件较大,上传过程中可能遇到网络切换、页面关闭或请求超时。
对于大文件,建议进一步考虑:
如果只是小型工单附件,没有必要一开始就实现完整的分片系统。架构复杂度应与业务价值匹配。
视频上传方案没有统一答案,可以先回答三个问题:
如果视频只是临时沟通材料,上传前压缩通常更轻量;如果原文件属于核心资产,更适合对象存储直传;如果视频需要公开播放,则应增加异步转码和多版本输出。
先确定视频在业务中的用途,再选择上传架构,比单纯把文件限制调大更可靠。