This commit is contained in:
2026-03-27 22:54:58 -03:00
parent 3d8e7291f3
commit 94c7b21ae5
8 changed files with 233 additions and 224 deletions

View File

@@ -13,22 +13,6 @@ class AssetStatus(models.TextChoices):
ERROR = "error", "Error"
class JobStatus(models.TextChoices):
PENDING = "pending", "Pending"
PROCESSING = "processing", "Processing"
COMPLETED = "completed", "Completed"
FAILED = "failed", "Failed"
CANCELLED = "cancelled", "Cancelled"
class ChunkJobStatus(models.TextChoices):
PENDING = "pending", "Pending"
CHUNKING = "chunking", "Chunking"
PROCESSING = "processing", "Processing"
COLLECTING = "collecting", "Collecting"
COMPLETED = "completed", "Completed"
FAILED = "failed", "Failed"
CANCELLED = "cancelled", "Cancelled"
class DetectJobStatus(models.TextChoices):
PENDING = "pending", "Pending"
RUNNING = "running", "Running"
PAUSED = "paused", "Paused"
@@ -111,81 +95,17 @@ class TranscodePreset(models.Model):
return self.name
class TranscodeJob(models.Model):
"""A transcoding or trimming job in the queue."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
source_asset_id = models.UUIDField()
preset_id = models.UUIDField(null=True, blank=True)
preset_snapshot = models.JSONField(default=dict, blank=True)
trim_start = models.FloatField(null=True, blank=True, default=None)
trim_end = models.FloatField(null=True, blank=True, default=None)
output_filename = models.CharField(max_length=500)
output_path = models.CharField(max_length=1000, null=True, blank=True)
output_asset_id = models.UUIDField(null=True, blank=True)
status = models.CharField(max_length=20, choices=JobStatus.choices, default=JobStatus.PENDING)
progress = models.FloatField(default=0.0)
current_frame = models.IntegerField(null=True, blank=True, default=None)
current_time = models.FloatField(null=True, blank=True, default=None)
speed = models.CharField(max_length=255, null=True, blank=True)
error_message = models.TextField(blank=True, default='')
celery_task_id = models.CharField(max_length=255, null=True, blank=True)
execution_arn = models.CharField(max_length=255, null=True, blank=True)
priority = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
started_at = models.DateTimeField(null=True, blank=True)
completed_at = models.DateTimeField(null=True, blank=True)
class Meta:
ordering = ["-created_at"]
def __str__(self):
return str(self.id)
class ChunkJob(models.Model):
"""A chunk pipeline job — splits a media file into chunks and processes them"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
source_asset_id = models.UUIDField()
chunk_duration = models.FloatField(default=10.0)
num_workers = models.IntegerField(default=4)
max_retries = models.IntegerField(default=3)
processor_type = models.CharField(max_length=255)
status = models.CharField(max_length=20, choices=ChunkJobStatus.choices, default=ChunkJobStatus.PENDING)
progress = models.FloatField(default=0.0)
total_chunks = models.IntegerField(default=0)
processed_chunks = models.IntegerField(default=0)
failed_chunks = models.IntegerField(default=0)
retry_count = models.IntegerField(default=0)
error_message = models.TextField(blank=True, default='')
throughput_mbps = models.FloatField(null=True, blank=True, default=None)
elapsed_seconds = models.FloatField(null=True, blank=True, default=None)
celery_task_id = models.CharField(max_length=255, null=True, blank=True)
priority = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
started_at = models.DateTimeField(null=True, blank=True)
completed_at = models.DateTimeField(null=True, blank=True)
class Meta:
ordering = ["-created_at"]
def __str__(self):
return str(self.id)
class DetectJob(models.Model):
"""A detection pipeline job."""
class Job(models.Model):
"""A pipeline job."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
source_asset_id = models.UUIDField()
video_path = models.CharField(max_length=1000)
profile_name = models.CharField(max_length=255)
parent_job_id = models.UUIDField(null=True, blank=True)
parent_id = models.UUIDField(null=True, blank=True)
run_type = models.CharField(max_length=20, choices=RunType.choices, default=RunType.INITIAL)
replay_from_stage = models.CharField(max_length=255, null=True, blank=True)
config_overrides = models.JSONField(default=dict, blank=True)
status = models.CharField(max_length=20, choices=DetectJobStatus.choices, default=DetectJobStatus.PENDING)
status = models.CharField(max_length=20, choices=JobStatus.choices, default=JobStatus.PENDING)
current_stage = models.CharField(max_length=255, null=True, blank=True)
progress = models.FloatField(default=0.0)
error_message = models.TextField(blank=True, default='')
@@ -206,26 +126,17 @@ class DetectJob(models.Model):
return str(self.id)
class StageCheckpoint(models.Model):
"""A checkpoint saved after a pipeline stage completes."""
class Timeline(models.Model):
"""The frame sequence from a source video."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
job_id = models.UUIDField()
stage = models.CharField(max_length=255)
stage_index = models.IntegerField()
source_asset_id = models.UUIDField(null=True, blank=True)
source_video = models.CharField(max_length=255)
profile_name = models.CharField(max_length=255)
fps = models.FloatField(default=2.0)
frames_prefix = models.CharField(max_length=255)
frames_manifest = models.JSONField(default=dict, blank=True)
frames_meta = models.JSONField(default=list, blank=True)
filtered_frame_sequences = models.JSONField(default=list, blank=True)
boxes_by_frame = models.JSONField(default=dict, blank=True)
text_candidates = models.JSONField(default=list, blank=True)
unresolved_candidates = models.JSONField(default=list, blank=True)
detections = models.JSONField(default=list, blank=True)
stats = models.JSONField(default=dict, blank=True)
config_snapshot = models.JSONField(default=dict, blank=True)
config_overrides = models.JSONField(default=dict, blank=True)
video_path = models.CharField(max_length=1000)
profile_name = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
@@ -235,15 +146,36 @@ class StageCheckpoint(models.Model):
return str(self.id)
class KnownBrand(models.Model):
class Checkpoint(models.Model):
"""A snapshot of pipeline state on a timeline."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
timeline_id = models.UUIDField()
parent_id = models.UUIDField(null=True, blank=True)
stage_outputs = models.JSONField(default=dict, blank=True)
config_overrides = models.JSONField(default=dict, blank=True)
stats = models.JSONField(default=dict, blank=True)
is_scenario = models.BooleanField(default=False)
scenario_label = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-created_at"]
def __str__(self):
return str(self.id)
class Brand(models.Model):
"""A brand discovered or registered in the system."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
canonical_name = models.CharField(max_length=255)
aliases = models.JSONField(default=list, blank=True)
first_source = models.CharField(max_length=20, choices=BrandSource.choices, default=BrandSource.OCR)
total_occurrences = models.IntegerField(default=0)
source = models.CharField(max_length=20, choices=BrandSource.choices, default=BrandSource.OCR)
confirmed = models.BooleanField(default=False)
airings = models.JSONField(default=list, blank=True)
total_airings = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@@ -253,24 +185,3 @@ class KnownBrand(models.Model):
def __str__(self):
return str(self.id)
class SourceBrandSighting(models.Model):
"""A brand seen in a specific source (video/asset)."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
source_asset_id = models.UUIDField()
brand_id = models.UUIDField()
brand_name = models.CharField(max_length=255)
first_seen_timestamp = models.FloatField(default=0.0)
last_seen_timestamp = models.FloatField(default=0.0)
occurrences = models.IntegerField(default=0)
detection_source = models.CharField(max_length=20, choices=BrandSource.choices, default=BrandSource.OCR)
avg_confidence = models.FloatField(default=0.0)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-created_at"]
def __str__(self):
return str(self.id)