如何在Django后端从audio/mp4 Blob获取音频时长并限制为30秒
解决方案:无文件化获取音频时长并限制30秒
前端预校验(优先做,大幅减少后端压力)
在发送请求前先在前端完成时长校验,避免无效请求:
- 方法1:直接追踪录制时长
启动录制时记录时间戳,停止时计算时长差值,超过30秒直接拦截请求:let startTime; const mediaRecorder = new MediaRecorder(stream); mediaRecorder.start(); startTime = Date.now(); mediaRecorder.addEventListener('stop', () => { const duration = (Date.now() - startTime) / 1000; if (duration > 30) { alert('音频时长不能超过30秒'); return; } // 发送Blob到后端 const formData = new FormData(); formData.append('audio', blob); fetch('/upload-audio/', { method: 'POST', body: formData }); }); - 方法2:用AudioContext解析精确时长
若需要更精准的时长(比如处理已录制好的Blob),用AudioContext解码音频数据:async function checkAudioDuration(blob) { const arrayBuffer = await blob.arrayBuffer(); const audioContext = new (window.AudioContext || window.webkitAudioContext)(); const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); return audioBuffer.duration; } // 使用示例 checkAudioDuration(blob).then(duration => { if (duration > 30) { alert('音频时长不能超过30秒'); return; } // 发送请求 });
后端解析二进制数据(兜底校验,防止前端校验被绕过)
直接在内存中处理Blob二进制数据,无需写入文件即可计算时长:
处理WAV格式(推荐,可配置MediaRecorder录制为WAV)
用Python内置wave模块结合BytesIO解析:
from django.http import JsonResponse from io import BytesIO import wave def upload_audio(request): if request.method == 'POST': audio_blob = request.FILES['audio'].read() # 内存中解析WAV头信息 try: with wave.open(BytesIO(audio_blob), 'rb') as wav_file: frames = wav_file.getnframes() sample_rate = wav_file.getframerate() duration = frames / sample_rate if duration > 30: return JsonResponse({'error': '音频时长不能超过30秒'}, status=400) # 存入BinaryField # your_model_instance.audio_data = audio_blob # your_model_instance.save() return JsonResponse({'success': True}) except wave.Error: return JsonResponse({'error': '无效的WAV文件'}, status=400)
处理WebM格式(前端默认录制格式)
若前端录制的是WebM,用pydub库(需依赖FFmpeg)在内存中解析:
from django.http import JsonResponse from io import BytesIO from pydub import AudioSegment def upload_audio(request): if request.method == 'POST': audio_blob = request.FILES['audio'].read() try: audio = AudioSegment.from_file(BytesIO(audio_blob), format='webm') duration = audio.duration_seconds if duration > 30: return JsonResponse({'error': '音频时长不能超过30秒'}, status=400) # 存入BinaryField # your_model_instance.audio_data = audio_blob # your_model_instance.save() return JsonResponse({'success': True}) except Exception as e: return JsonResponse({'error': f'解析音频失败: {str(e)}'}, status=400)
额外提示
- 前端尽量配置MediaRecorder录制WAV,降低后端解析复杂度:
const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/wav' }); - 后端校验必须保留,防止前端校验被篡改或绕过。
内容的提问来源于stack exchange,提问作者Weilory
相关产品推荐
相关产品推荐

