Coverage for apps/scene.py: 100%

43 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-09 04:47 +0000

1""" 

2Scene information for video generation apps. 

3TODO consolidate info and segment. 

4TODO make it JSON encode/decode friendly for saving/loading from disk or database 

5""" 

6 

7from typing import List 

8from typing import Optional 

9 

10from dataclasses import dataclass 

11from dataclasses import field 

12 

13 

14def format_time(seconds: float) -> str: 

15 """Format seconds as HH:MM:SS.""" 

16 minutes, secs = divmod(int(seconds), 60) 

17 hours, minutes = divmod(minutes, 60) 

18 return f"{hours:02d}:{minutes:02d}:{secs:02d}" 

19 

20 

21@dataclass 

22class SceneSegment: 

23 """A scene segment in a video.""" 

24 scene_id: int 

25 start_frame: int 

26 end_frame: int 

27 start_sec: float 

28 end_sec: float 

29 

30 frame_image_paths: List[str] = field(default_factory=list) 

31 descriptions: List[str] = field(default_factory=list) 

32 

33 audio_path: Optional[str] = None 

34 transcript: Optional[str] = None 

35 language: Optional[str] = None 

36 translation: Optional[str] = None 

37 

38 def add_image_path( 

39 self, 

40 image_path: str 

41 ) -> None: 

42 if image_path: 

43 self.frame_image_paths.append(image_path) 

44 

45 def add_description( 

46 self, 

47 description: str 

48 ) -> None: 

49 if description: 

50 self.descriptions.append(description) 

51 

52 def get_start(self) -> str: 

53 return format_time(self.start_sec) 

54 

55 def get_end(self) -> str: 

56 return format_time(self.end_sec) 

57 

58 @property 

59 def duration_sec(self) -> float: 

60 return self.end_sec - self.start_sec 

61 

62 def __str__(self) -> str: 

63 ret = f"[{self.start_frame:4d}-{self.end_frame:4d}, {self.start_sec:4.1f}-{self.end_sec:4.1f}]" 

64 if self.transcript: 

65 ret += f": {self.transcript[0:60]}..." 

66 for description in self.descriptions: 

67 ret += f" | {description[0:60]}..." 

68 if self.frame_image_paths: 

69 ret += f" | {len(self.frame_image_paths)} images" 

70 return ret