6565 get_tasks_status_grouped_by_task_name ,
6666 merge_tasks_status ,
6767)
68+ from ..flows .tasks import ExtractChapterFramesTask
6869from ..flows .models import FlowMetadata
6970from ..invenio_deposit .api import Deposit , has_status , preserve
7071from ..invenio_deposit .utils import mark_as_action
7677)
7778from ..records .minters import cds_doi_generator , is_local_doi , report_number_minter
7879from ..records .resolver import record_resolver
79- from ..records .utils import is_record , lowercase_value
80+ from ..records .utils import is_record , lowercase_value , parse_video_chapters
8081from ..records .validators import PartialDraft4Validator
8182from ..records .permissions import is_public
8283from .errors import DiscardConflict
@@ -504,7 +505,7 @@ def create(cls, data, id_=None, **kwargs):
504505 data .setdefault ("_access" , {})
505506 access_update = data ["_access" ].setdefault ("update" , [])
506507 try :
507- if current_user .email not in access_update :
508+ if current_user .email not in access_update :
508509 # Add the current user to the ``_access.update`` list
509510 access_update .append (current_user .email )
510511 except AttributeError :
@@ -905,11 +906,84 @@ def _publish_edited(self):
905906
906907 return super (Video , self )._publish_edited ()
907908
909+ def _has_chapters_changed (self , old_record = None ):
910+ """Check if chapters in description have changed."""
911+ current_description = self .get ("description" , "" )
912+ current_chapters = parse_video_chapters (current_description )
913+
914+ if old_record is None :
915+ # First publish - trigger if chapters exist
916+ return len (current_chapters ) > 0
917+
918+ old_description = old_record .get ("description" , "" )
919+ old_chapters = parse_video_chapters (old_description )
920+
921+ # Compare chapter timestamps and titles
922+ if len (current_chapters ) != len (old_chapters ):
923+ return True
924+
925+ for curr , old in zip (current_chapters , old_chapters ):
926+ if curr ["seconds" ] != old ["seconds" ] or curr ["title" ] != old ["title" ]:
927+ return True
928+
929+ return False
930+
931+ def _trigger_chapter_frame_extraction (self ):
932+ """Trigger chapter frame extraction asynchronously for existing video files."""
933+ try :
934+ # Find the master video file
935+ master_file = CDSVideosFilesIterator .get_master_video_file (self )
936+
937+ if master_file is None :
938+ current_app .logger .warning (
939+ f"No master video file found for video { self .id } "
940+ )
941+ return
942+
943+ # Get the current flow for this deposit
944+ current_flow = FlowMetadata .get_by_deposit (self ["_deposit" ]["id" ])
945+
946+ if current_flow is None :
947+ current_app .logger .warning (
948+ f"No current flow found for video { self .id } . Cannot trigger chapter frame extraction."
949+ )
950+ return
951+
952+ current_app .logger .info (
953+ f"Triggering asynchronous ExtractChapterFramesTask for video { self .id } with flow { current_flow .id } "
954+ )
955+
956+ payload = current_flow .payload .copy ()
957+
958+ current_app .logger .info (f"Submitting ExtractChapterFramesTask with payload: { payload } " )
959+
960+ ExtractChapterFramesTask ().s (** payload ).apply_async ()
961+
962+ current_app .logger .info (
963+ f"ExtractChapterFramesTask submitted asynchronously for video { self .id } , flow_id: { current_flow .id } "
964+ )
965+ except Exception as e :
966+ current_app .logger .error (
967+ f"Failed to trigger async chapter frame extraction for video { self .id } : { e } "
968+ )
969+ import traceback
970+
971+ current_app .logger .error (f"Traceback: { traceback .format_exc ()} " )
972+
908973 @mark_as_action
909974 def publish (self , pid = None , id_ = None , ** kwargs ):
910975 """Publish a video and update the related project."""
911976 # save a copy of the old PID
912977 video_old_id = self ["_deposit" ]["id" ]
978+
979+ # Check if this is a republish and get the old record
980+ old_record = None
981+ try :
982+ _ , old_record = self .fetch_published ()
983+ except :
984+ # First publish
985+ pass
986+
913987 try :
914988 self ["category" ] = self .project ["category" ]
915989 self ["type" ] = self .project ["type" ]
@@ -930,6 +1004,13 @@ def publish(self, pid=None, id_=None, **kwargs):
9301004 video_published = super (Video , self ).publish (pid = pid , id_ = id_ , ** kwargs )
9311005 _ , record_new = self .fetch_published ()
9321006
1007+ # Check if chapters have changed and trigger frame extraction
1008+ if self ._has_chapters_changed (old_record ):
1009+ current_app .logger .info (
1010+ f"Chapters changed for video { self .id } , triggering frame extraction"
1011+ )
1012+ self ._trigger_chapter_frame_extraction ()
1013+
9331014 # update associated project
9341015 video_published .project ._update_videos (
9351016 [video_build_url (video_old_id )],
@@ -1088,7 +1169,6 @@ def _create_tags(self):
10881169 except IndexError :
10891170 return
10901171
1091-
10921172 def mint_doi (self ):
10931173 """Mint DOI."""
10941174 assert self .has_record ()
@@ -1109,7 +1189,7 @@ def mint_doi(self):
11091189 status = PIDStatus .RESERVED ,
11101190 )
11111191 return self
1112-
1192+
11131193
11141194project_resolver = Resolver (
11151195 pid_type = "depid" ,
0 commit comments