Browse Source

media duration auto calculate feature added

master
Mohsen Taba 1 week ago
parent
commit
b882791f0f
  1. 33
      apps/podcast/models.py
  2. 33
      apps/video/models.py
  3. 38
      utils/media.py

33
apps/podcast/models.py

@ -105,7 +105,40 @@ class Podcast(LowercaseSlugMixin, models.Model):
return self.view_count
def save(self, *args, **kwargs):
is_new = self.pk is None
file_changed = False
if not is_new:
try:
old_instance = Podcast.objects.get(pk=self.pk)
if old_instance.audio_file != self.audio_file:
file_changed = True
except Podcast.DoesNotExist:
pass
else:
file_changed = True
if not self.audio_time:
import datetime
self.audio_time = datetime.time(0, 0, 0)
super().save(*args, **kwargs)
if (file_changed or self.audio_time == datetime.time(0, 0, 0)) and self.audio_file:
from utils.media import get_media_duration_time
try:
duration_time = get_media_duration_time(self.audio_file.path)
if duration_time:
self.audio_time = duration_time
Podcast.objects.filter(pk=self.pk).update(audio_time=duration_time)
# Update playlists that contain this podcast
for appearance in self.playlist_appearances.all():
playlist = appearance.playlist
playlist.total_time = playlist.calculate_total_time()
playlist.save(update_fields=['total_time'])
except Exception as e:
pass

33
apps/video/models.py

@ -125,7 +125,40 @@ class Video(LowercaseSlugMixin, models.Model):
})
def save(self, *args, **kwargs):
is_new = self.pk is None
file_changed = False
if not is_new:
try:
old_instance = Video.objects.get(pk=self.pk)
if old_instance.video_file != self.video_file:
file_changed = True
except Video.DoesNotExist:
pass
else:
file_changed = True
if not self.video_time:
import datetime
self.video_time = datetime.time(0, 0, 0)
super().save(*args, **kwargs)
if (file_changed or self.video_time == datetime.time(0, 0, 0)) and self.video_file and self.video_type == self.VedioTypeChoices.VIDEO_FILE:
from utils.media import get_media_duration_time
try:
duration_time = get_media_duration_time(self.video_file.path)
if duration_time:
self.video_time = duration_time
Video.objects.filter(pk=self.pk).update(video_time=duration_time)
# Update playlists that contain this video
for appearance in self.playlist_appearances.all():
playlist = appearance.playlist
playlist.total_time = playlist.calculate_total_time()
playlist.save(update_fields=['total_time'])
except Exception as e:
pass

38
utils/media.py

@ -0,0 +1,38 @@
import datetime
import logging
from tinytag import TinyTag
logger = logging.getLogger(__name__)
def get_media_duration_seconds(file_path):
"""
Given a local file path, reads the duration using tinytag.
Returns duration in seconds (float) or None if error occurs.
"""
try:
tag = TinyTag.get(file_path)
return tag.duration
except Exception as e:
logger.error(f"Error reading media duration for {file_path}: {e}")
return None
def get_media_duration_time(file_path):
"""
Given a local file path, reads the duration and returns a datetime.time object.
Caps hours at 23 to comply with Django TimeField limits.
"""
duration_seconds = get_media_duration_seconds(file_path)
if duration_seconds is None:
return None
seconds = int(duration_seconds)
hours = seconds // 3600
if hours > 23:
hours = 23
minutes = 59
secs = 59
else:
minutes = (seconds % 3600) // 60
secs = seconds % 60
return datetime.time(hour=hours, minute=minutes, second=secs)
Loading…
Cancel
Save