Generate per-scene image timecodes using PTS-accurate seconds-based timing. `frame_margin` accepts any :data:`TimecodeLike` value (e.g. ``int`` frames, ``float`` seconds, or ``str`` such as ``"0.1s"``).
(
scene_list: SceneList,
num_images: int,
frame_margin: TimecodeLike,
)
| 36 | |
| 37 | |
| 38 | def _generate_timecode_list( |
| 39 | scene_list: SceneList, |
| 40 | num_images: int, |
| 41 | frame_margin: TimecodeLike, |
| 42 | ) -> list[list[FrameTimecode]]: |
| 43 | """Generate per-scene image timecodes using PTS-accurate seconds-based timing. |
| 44 | |
| 45 | `frame_margin` accepts any :data:`TimecodeLike` value (e.g. ``int`` frames, ``float`` |
| 46 | seconds, or ``str`` such as ``"0.1s"``). |
| 47 | """ |
| 48 | frame_rate = scene_list[0][0].frame_rate |
| 49 | assert frame_rate is not None |
| 50 | margin_secs = FrameTimecode(timecode=frame_margin, fps=frame_rate).seconds |
| 51 | result = [] |
| 52 | for start, end in scene_list: |
| 53 | duration_secs = (end - start).seconds |
| 54 | if duration_secs <= 0: |
| 55 | result.append([start] * num_images) |
| 56 | continue |
| 57 | segment_secs = duration_secs / num_images |
| 58 | timecodes = [] |
| 59 | for j in range(num_images): |
| 60 | seg_start = start.seconds + j * segment_secs |
| 61 | seg_end = start.seconds + (j + 1) * segment_secs |
| 62 | if num_images == 1: |
| 63 | t = start.seconds + duration_secs / 2.0 |
| 64 | elif j == 0: |
| 65 | t = min(seg_start + margin_secs, seg_end) |
| 66 | elif j == num_images - 1: |
| 67 | t = max(seg_end - margin_secs, seg_start) |
| 68 | else: |
| 69 | t = (seg_start + seg_end) / 2.0 |
| 70 | timecodes.append(FrameTimecode(t, fps=frame_rate)) |
| 71 | result.append(timecodes) |
| 72 | return result |
| 73 | |
| 74 | |
| 75 | def _scale_image( |
no test coverage detected