在Django中获取数据库存储视频的时长(已知title、URL、PK)
嘿,这个需求我刚好在项目里实现过,给你几个实用的方案,根据你的视频存储方式来选:
方案1:本地存储的视频(服务器Media目录下)
如果你的视频是存在Django的MEDIA_ROOT目录里的,推荐用moviepy库来读取视频元数据,操作起来很方便。
步骤:
先安装依赖:
pip install moviepy(
moviepy依赖FFmpeg,所以服务器上需要先安装FFmpeg,Ubuntu可以用apt install ffmpeg,CentOS用yum install ffmpeg)在你的Video模型里加一个字段存储时长,然后在保存时自动计算:
from django.db import models from moviepy.editor import VideoFileClip import os from django.conf import settings class Video(models.Model): title = models.CharField(max_length=200) video_file = models.FileField(upload_to='videos/') pk = models.AutoField(primary_key=True) duration = models.FloatField(null=True, blank=True) # 单位:秒 def save(self, *args, **kwargs): # 只有当视频文件更新且时长未设置时才计算 if self.video_file and not self.duration: file_path = os.path.join(settings.MEDIA_ROOT, self.video_file.name) try: with VideoFileClip(file_path) as clip: self.duration = clip.duration # 获取秒数 except Exception as e: print(f"计算时长失败: {str(e)}") # 可以根据需求设置默认值或者抛出异常 super().save(*args, **kwargs) def get_formatted_duration(self): # 把秒数转成 HH:MM:SS 的友好格式 minutes, seconds = divmod(int(self.duration), 60) hours, minutes = divmod(minutes, 60) return f"{hours:02d}:{minutes:02d}:{seconds:02d}"这样每次上传视频时,时长就会自动存在
duration字段里,之后直接调用video.get_formatted_duration()就能拿到格式化后的时长了。
方案2:远程URL的视频(第三方托管/外部链接)
如果视频是存在外部服务器(比如云存储、YouTube等),有两种方式:
方式A:调用第三方平台API(推荐)
比如YouTube可以用Data API获取视频时长,阿里云OSS可以用对象存储API获取文件元数据,这种方式最可靠,不会出现解析错误。具体API用法要看对应平台的文档,比如YouTube的API只需要传入视频ID就能拿到时长。
方式B:用FFmpeg解析远程URL
如果没有API可用,可以用FFmpeg直接读取远程视频的元数据,在Python里用subprocess执行命令:
import subprocess import re def get_remote_video_duration(video_url): try: # 执行FFmpeg命令,从stderr提取时长信息(FFmpeg默认把元数据输出到stderr) result = subprocess.run( ["ffmpeg", "-i", video_url], stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True ) # 正则匹配Duration字段 duration_match = re.search(r'Duration: (\d+:\d+:\d+\.\d+)', result.stderr) if duration_match: duration_str = duration_match.group(1) # 转成秒数 hours, minutes, seconds = duration_str.split(':') total_seconds = int(hours)*3600 + int(minutes)*60 + float(seconds) return total_seconds return None except Exception as e: print(f"获取远程视频时长失败: {str(e)}") return None
注意:这种方式要考虑网络超时、URL权限(比如带签名的链接)问题,而且如果视频很大,FFmpeg会下载部分内容来解析,可能会有性能损耗,所以建议把计算后的时长存到数据库里,不要每次请求都计算。
额外建议
- 优先把时长存到数据库:不管哪种方式,都建议在视频入库/更新时计算好时长并存到字段里,避免每次请求都重复计算,提升性能。
- 异常处理:计算时长时一定要加异常捕获,避免因为视频损坏、路径错误等导致程序崩溃。
- 格式转换:如果需要展示友好的时长格式(比如1小时23分),可以写个辅助方法来转换秒数。
内容的提问来源于stack exchange,提问作者webdev
相关产品推荐
相关产品推荐

