from django.db import models, transaction from django.urls import reverse from django.conf import settings from aliyun_video.core import get_video_play_info from aliyun_video.core.utils import ( get_path_from_cdn_url, get_play_id_from_web_m3u8, build_m3u8_index ) class AliyunVideo(models.Model): STATUS_PROCESSING = 0 STATUS_NORMAL = 1 STATUS_CHOICES = ( (STATUS_PROCESSING, 'processing'), (STATUS_NORMAL, 'normal') ) lesson_id = models.IntegerField() video_id = models.CharField(max_length=64, primary_key=True, unique=True) title = models.CharField(max_length=128) cover_image_url = models.URLField(blank=True, null=True) duration = models.FloatField(blank=True, null=True, default=0) status = models.SmallIntegerField(choices=STATUS_CHOICES, default=STATUS_PROCESSING) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = 'aliyun_video' @property def log_url(self): return reverse( 'lecture:play-log', kwargs={ 'lesson_id': self.lesson_id, 'video_id': self.video_id }) class AliyunVideoPlayDetail(models.Model): video = models.ForeignKey( AliyunVideo, on_delete=models.CASCADE, related_name="video_play_details" ) play_id = models.CharField(max_length=128, unique=True) bit_rate = models.FloatField() definition = models.CharField(max_length=8) duration = models.FloatField(blank=True, null=True, default=0) width = models.IntegerField() height = models.IntegerField() class Meta: db_table = 'aliyun_video_play_details' @property def m3u8_index_content(self): return build_m3u8_index( self.video.lesson_id, self.video_id, self.play_id, self.duration, 10 ) @property def play_url(self): return reverse( 'lecture:play-m3u8', kwargs={ 'lesson_id': self.video.lesson_id, 'video_id': self.video_id, 'play_id': self.play_id }) def aliyun_transcode_event_callback(video_id): """ Update video infos: cover image, title, status Get and save all the transcoded videos. """ try: video = AliyunVideo.objects.get(video_id=video_id) # TODO: get_or_create except AliyunVideo.DoesNotExist: return video_info = get_video_play_info(video_id) with transaction.atomic(): video.cover_image_url = get_path_from_cdn_url(video_info['VideoBase']['CoverURL']) video.duration = video_info['VideoBase']['Duration'] video.title = video_info['VideoBase']['Title'] video.status = AliyunVideo.STATUS_NORMAL video.save() video.video_play_details.all().delete() for play_info in video_info['PlayInfoList']['PlayInfo']: if play_info['Format'].lower() != 'm3u8': continue play_id = get_play_id_from_web_m3u8(play_info['PlayURL']) AliyunVideoPlayDetail.objects.create( video=video, play_id=play_id, bit_rate=play_info['Bitrate'], definition=play_info['Definition'], duration=play_info['Duration'], width=play_info['Width'], height=play_info['Height'] ) class AliyunVideoHistory(models.Model): video = models.ForeignKey( AliyunVideo, on_delete=models.DO_NOTHING) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING) first_visited_at = models.DateTimeField(auto_now_add=True) last_visited_at = models.DateTimeField(auto_now=True) total_visited_count = models.IntegerField(default=0) played_at = models.FloatField(default=0) last_definition = models.CharField(max_length=16, blank=True, null=True) class Meta: db_table = 'aliyun_video_history' unique_together = ('video', 'user')