Django中如何将浏览器录制的Blob转为MP4并保存到服务器
解决浏览器录制视频后在Django服务器保存为MP4的问题
一、前端确保录制并传输MP4格式
MediaRecorder默认编码不一定是MP4,先在前端指定兼容的MIME类型,让录制的Blob直接为MP4格式:
- 先验证浏览器支持性:
const mimeType = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'; if (!MediaRecorder.isTypeSupported(mimeType)) { console.error('浏览器不支持MP4录制'); alert('当前浏览器不支持MP4格式录制,请更换Chrome或Edge'); return; }
- 修改MediaRecorder初始化代码:
把原来的recorder = new MediaRecorder(stream)替换为:
recorder = new MediaRecorder(stream, { mimeType: mimeType });
- 传输时指定文件名和类型:
构建FormData时明确Blob的类型与文件名,方便后端识别:
const videoBlob = new Blob(blobContainer, { type: mimeType }); var formdata = new FormData(); formdata.append('blobFile', videoBlob, `recording_${Date.now()}.mp4`);
二、Django后端保存MP4文件
情况1:前端已传输MP4格式
若前端确保传的是MP4,直接用Django的FileField保存即可:
- 确保模型配置正确:
from django.db import models class VideoUpload(models.Model): name = models.CharField(max_length=100) video = models.FileField(upload_to='recordings/') # 文件会存在MEDIA_ROOT/recordings目录下 created_at = models.DateTimeField(auto_now_add=True)
- 优化视图(替换
@csrf_exempt,改用安全的CSRF Token传递):
先在前端fetch请求中添加CSRF Token:
// 从Cookie中获取Django默认的CSRF Token function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } // 修改fetch请求 fetch('/upload', { method: 'POST', headers: { 'X-CSRFToken': getCookie('csrftoken'), }, body: formdata }).then(()=>{ alert('视频已上传'); })
然后更新视图函数:
from django.shortcuts import redirect from django.http import HttpResponseBadRequest from .models import VideoUpload def upload(request): if request.method != 'POST': return HttpResponseBadRequest('仅支持POST请求') if 'blobFile' not in request.FILES: return HttpResponseBadRequest('未上传视频文件') video_file = request.FILES['blobFile'] # 可选:验证文件类型 if not video_file.name.endswith('.mp4') or video_file.content_type != 'video/mp4': return HttpResponseBadRequest('仅支持MP4格式视频') video_upload = VideoUpload() video_upload.video = video_file video_upload.name = request.user.username video_upload.save() # 后续给Whisper用可直接取路径:video_upload.video.path return redirect('/')
情况2:后端转码为MP4(兼容不支持MP4录制的浏览器)
若部分浏览器无法录制MP4,用FFmpeg在后端转码:
- 安装依赖:
服务器安装FFmpeg(Ubuntu:sudo apt install ffmpeg),再安装Python库:
pip install ffmpeg-python
- 带转码逻辑的视图:
import os import datetime from django.conf import settings from django.shortcuts import redirect from django.http import HttpResponseBadRequest from django.core.files import File from .models import VideoUpload import ffmpeg def upload(request): if request.method != 'POST': return HttpResponseBadRequest('仅支持POST请求') if 'blobFile' not in request.FILES: return HttpResponseBadRequest('未上传视频文件') temp_file = request.FILES['blobFile'] # 临时保存原始文件 temp_dir = os.path.join(settings.MEDIA_ROOT, 'temp') os.makedirs(temp_dir, exist_ok=True) temp_path = os.path.join(temp_dir, temp_file.name) with open(temp_path, 'wb+') as f: for chunk in temp_file.chunks(): f.write(chunk) # 转码为MP4 mp4_filename = f'recording_{datetime.datetime.now().timestamp()}.mp4' mp4_path = os.path.join(settings.MEDIA_ROOT, 'recordings', mp4_filename) try: ffmpeg.input(temp_path).output(mp4_path, vcodec='libx264', acodec='aac').run() except Exception as e: os.remove(temp_path) return HttpResponseBadRequest(f'转码失败:{str(e)}') # 删除临时文件 os.remove(temp_path) # 保存到模型 video_upload = VideoUpload() with open(mp4_path, 'rb') as f: video_upload.video.save(mp4_filename, File(f), save=False) video_upload.name = request.user.username video_upload.save() return redirect('/')
三、给Whisper转录用的注意点
保存后的MP4文件可通过video_upload.video.path获取绝对路径,直接传给Whisper:
import whisper model = whisper.load_model("base") result = model.transcribe(video_upload.video.path) print(result["text"])
内容的提问来源于stack exchange,提问作者pcol01
相关产品推荐
相关产品推荐

