|
24 | 24 | from config import LOCAL_STORAGE_PATH |
25 | 25 | logger = logging.getLogger(__name__) |
26 | 26 |
|
27 | | -def process_image_to_video(image_url, length, frame_rate, zoom_speed, job_id, webhook_url=None): |
| 27 | +def process_image_to_video(image_url, length, frame_rate, zoom_speed, job_id, webhook_url=None, zoom_effect="linear", zoom_loop_duration=None): |
28 | 28 | try: |
29 | 29 | # Download the image file |
30 | 30 | image_path = download_file(image_url, LOCAL_STORAGE_PATH) |
@@ -52,12 +52,25 @@ def process_image_to_video(image_url, length, frame_rate, zoom_speed, job_id, we |
52 | 52 |
|
53 | 53 | logger.info(f"Using scale dimensions: {scale_dims}, output dimensions: {output_dims}") |
54 | 54 | logger.info(f"Video length: {length}s, Frame rate: {frame_rate}fps, Total frames: {total_frames}") |
55 | | - logger.info(f"Zoom speed: {zoom_speed}/s, Final zoom factor: {zoom_factor}") |
| 55 | + logger.info(f"Zoom speed: {zoom_speed}/s, Final zoom factor: {zoom_factor}, Effect: {zoom_effect}, Loop Duration: {zoom_loop_duration}") |
56 | 56 |
|
57 | 57 | # Prepare FFmpeg command with fps filter to ensure correct frame rate |
| 58 | + if zoom_effect == "ping-pong": |
| 59 | + # Using triangle wave for Ping-Pong Zoom (In -> Out) with optional loop frequency |
| 60 | + loop_period = zoom_loop_duration if zoom_loop_duration else length |
| 61 | + loop_frames = int(loop_period * frame_rate) |
| 62 | + if loop_frames < 1: loop_frames = total_frames |
| 63 | + |
| 64 | + # Formula: 1 + MaxCorrection * (1 - abs(2 * mod(on, loop_frames)/loop_frames - 1)) |
| 65 | + # mod(on, loop_frames) cycles 0 -> loop_frames-1 |
| 66 | + expression = f"1+({zoom_speed}*{length})*(1-abs(2*mod(on,{loop_frames})/{loop_frames}-1))" |
| 67 | + else: # linear default |
| 68 | + # Standard linear zoom in |
| 69 | + expression = f"min(1+({zoom_speed}*{length})*on/{total_frames}, {zoom_factor})" |
| 70 | + |
58 | 71 | cmd = [ |
59 | 72 | 'ffmpeg', '-framerate', str(frame_rate), '-loop', '1', '-i', image_path, |
60 | | - '-vf', f"scale={scale_dims},zoompan=z='min(1+({zoom_speed}*{length})*on/{total_frames}, {zoom_factor})':d={total_frames}:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s={output_dims},fps={frame_rate}", |
| 73 | + '-vf', f"scale={scale_dims},zoompan=z='{expression}':d={total_frames}:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s={output_dims},fps={frame_rate}", |
61 | 74 | '-c:v', 'libx264', '-r', str(frame_rate), '-t', str(length), '-pix_fmt', 'yuv420p', output_path |
62 | 75 | ] |
63 | 76 |
|
|
0 commit comments