@@ -527,6 +527,93 @@ def index_scenes(
527527 return None
528528 return scenes_data .get ("scene_index_id" )
529529
530+ def index_visuals (
531+ self ,
532+ prompt : Optional [str ] = None ,
533+ batch_config : Optional [Dict ] = None ,
534+ model_name : Optional [str ] = None ,
535+ model_config : Optional [Dict ] = None ,
536+ name : Optional [str ] = None ,
537+ callback_url : Optional [str ] = None ,
538+ ) -> Optional [str ]:
539+ """Index visuals (scenes) from the video.
540+
541+ :param str prompt: Prompt for scene description
542+ :param dict batch_config: Frame extraction config with keys:
543+ - "type": Extraction type ("time" or "shot"). Default is "time".
544+ - "value": Window size in seconds (for time) or threshold (for shot). Default is 10.
545+ - "frame_count": Number of frames to extract per window. Default is 1.
546+ - "select_frames": Which frames to select (e.g., ["first", "middle", "last"]). Default is ["first"].
547+ :param str model_name: Name of the model
548+ :param dict model_config: Configuration for the model
549+ :param str name: Name of the visual index
550+ :param str callback_url: URL to receive the callback (optional)
551+ :return: The scene index id
552+ :rtype: str
553+ """
554+ if batch_config is None :
555+ batch_config = {"type" : "time" , "value" : 10 , "frame_count" : 1 }
556+
557+ extraction_type = batch_config .get ("type" , "time" )
558+ if extraction_type == "shot" :
559+ extraction_type = SceneExtractionType .shot_based
560+ extraction_config = {
561+ "threshold" : batch_config .get ("value" , 20 ),
562+ "frame_count" : batch_config .get ("frame_count" , 1 ),
563+ }
564+ else :
565+ extraction_type = SceneExtractionType .time_based
566+ extraction_config = {
567+ "time" : batch_config .get ("value" , 10 ),
568+ "frame_count" : batch_config .get ("frame_count" , 1 ),
569+ "select_frames" : batch_config .get ("select_frames" , ["first" ]),
570+ }
571+
572+ scenes_data = self ._connection .post (
573+ path = f"{ ApiPath .video } /{ self .id } /{ ApiPath .index } /{ ApiPath .scene } " ,
574+ data = {
575+ "extraction_type" : extraction_type ,
576+ "extraction_config" : extraction_config ,
577+ "prompt" : prompt ,
578+ "model_name" : model_name ,
579+ "model_config" : model_config or {},
580+ "name" : name ,
581+ "callback_url" : callback_url ,
582+ },
583+ )
584+ if not scenes_data :
585+ return None
586+ return scenes_data .get ("scene_index_id" )
587+
588+ def index_audio (
589+ self ,
590+ language_code : Optional [str ] = None ,
591+ segmentation_type : Optional [SegmentationType ] = SegmentationType .sentence ,
592+ force : bool = False ,
593+ callback_url : str = None ,
594+ ) -> None :
595+ """Index audio (spoken words) in the video.
596+
597+ :param str language_code: (optional) Language code of the video
598+ :param SegmentationType segmentation_type: (optional) Segmentation type used for indexing, :class:`SegmentationType <SegmentationType>` object
599+ :param bool force: (optional) Force to index the video
600+ :param str callback_url: (optional) URL to receive the callback
601+ :raises InvalidRequestError: If the video is already indexed
602+ :return: None if the indexing is successful
603+ :rtype: None
604+ """
605+ self ._connection .post (
606+ path = f"{ ApiPath .video } /{ self .id } /{ ApiPath .index } " ,
607+ data = {
608+ "index_type" : IndexType .spoken_word ,
609+ "language_code" : language_code ,
610+ "segmentation_type" : segmentation_type ,
611+ "force" : force ,
612+ "callback_url" : callback_url ,
613+ },
614+ show_progress = True ,
615+ )
616+
530617 def list_scene_index (self ) -> List :
531618 """List all the scene indexes.
532619
0 commit comments