ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"experiment": "5-6",
|
||||
"run_id": "exp5-6-real-blender-20260730-055102",
|
||||
"manifest": "validation/runs/exp5-6-real-blender-20260730-055102/manifest.json",
|
||||
"manifest_sha256": "fd044738e812faa832863f4c112880a9583c268afb7d08f388c00623498ab7a8",
|
||||
"official_complete": true
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
本文件由 blender_editor.generate_bpy_script() 自动生成(实验 5-6)。
|
||||
执行:blender --background --python edit.py
|
||||
它把一条剪辑计划翻译成 Blender 视频序列编辑器(VSE)的 API 调用序列。
|
||||
"""
|
||||
import os
|
||||
import bpy
|
||||
|
||||
SRC = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/source_cache/big-buck-bunny-trailer-480p.mov'
|
||||
OUT = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/preflight-nospeed.mp4'
|
||||
FPS = 25
|
||||
START = 9.0 # 目标片段起点(秒)
|
||||
END = 11.0 # 目标片段终点(秒)
|
||||
SUBTITLE = 'BIG BUNNY' # None 或字幕文本
|
||||
SLOWMO = None # None 或放慢倍率(factor>1 表示放慢 factor 倍)
|
||||
|
||||
scene = bpy.context.scene
|
||||
scene.render.fps = FPS
|
||||
scene.render.fps_base = 1.0
|
||||
scene.render.resolution_x = 854
|
||||
scene.render.resolution_y = 480
|
||||
scene.render.resolution_percentage = 100
|
||||
|
||||
# 清掉可能存在的旧序列,保证幂等
|
||||
if scene.sequence_editor:
|
||||
bpy.ops.sequencer.select_all(action='SELECT')
|
||||
bpy.ops.sequencer.delete()
|
||||
se = scene.sequence_editor_create()
|
||||
|
||||
start_frame = int(round(START * FPS))
|
||||
dur_frames = max(1, int(round((END - START) * FPS)))
|
||||
|
||||
# 1) 导入影片 + 音轨(new_sound 在无音轨素材上会抛 RuntimeError,忽略即可)
|
||||
movie = se.sequences.new_movie(name="clip", filepath=SRC, channel=1, frame_start=1 - start_frame)
|
||||
try:
|
||||
sound = se.sequences.new_sound(name="audio", filepath=SRC, channel=2, frame_start=1 - start_frame)
|
||||
except RuntimeError:
|
||||
sound = None
|
||||
|
||||
# 2) 裁剪 [START, END]:偏移掉片头,再固定成片时长
|
||||
for strip in (movie, sound):
|
||||
if strip is None:
|
||||
continue
|
||||
strip.frame_offset_start = start_frame
|
||||
strip.frame_final_duration = dur_frames
|
||||
|
||||
top_channel = 3
|
||||
|
||||
# 3) 慢动作:SPEED 特效条(MULTIPLY 模式,speed_factor = 1/倍率)
|
||||
if SLOWMO:
|
||||
speed = se.sequences.new_effect(
|
||||
name="slowmo", type='SPEED', channel=top_channel,
|
||||
frame_start=1, frame_end=1 + dur_frames, seq1=movie,
|
||||
)
|
||||
speed.use_default_fade = False
|
||||
speed.speed_control = 'MULTIPLY'
|
||||
speed.speed_factor = 1.0 / SLOWMO
|
||||
top_channel += 1
|
||||
# 放慢后成片总帧数按倍率拉长
|
||||
render_dur = int(round(dur_frames * SLOWMO))
|
||||
movie.frame_final_duration = render_dur
|
||||
else:
|
||||
render_dur = dur_frames
|
||||
|
||||
# 4) 字幕:TEXT 特效条,底部居中带半透明底框
|
||||
if SUBTITLE:
|
||||
txt = se.sequences.new_effect(
|
||||
name="subtitle", type='TEXT', channel=top_channel,
|
||||
frame_start=1, frame_end=1 + render_dur,
|
||||
)
|
||||
txt.text = SUBTITLE
|
||||
txt.font_size = 100
|
||||
txt.location = (0.5, 0.12)
|
||||
txt.align_x = 'CENTER'
|
||||
txt.align_y = 'BOTTOM'
|
||||
txt.use_box = True
|
||||
txt.box_color = (0.0, 0.0, 0.0, 0.6)
|
||||
|
||||
# 5) 渲染范围 + 输出为 mp4(H.264+AAC)
|
||||
scene.frame_start = 1
|
||||
scene.frame_end = render_dur
|
||||
|
||||
r = scene.render
|
||||
r.image_settings.file_format = 'FFMPEG'
|
||||
r.ffmpeg.format = 'MPEG4'
|
||||
r.ffmpeg.codec = 'H264'
|
||||
r.ffmpeg.audio_codec = 'AAC'
|
||||
r.filepath = OUT
|
||||
os.makedirs(os.path.dirname(OUT) or ".", exist_ok=True)
|
||||
|
||||
bpy.ops.render.render(animation=True)
|
||||
print("BLENDER_RENDER_DONE", OUT)
|
||||
|
After Width: | Height: | Size: 371 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 364 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 366 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 342 KiB |
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
本文件由 blender_editor.generate_bpy_script() 自动生成(实验 5-6)。
|
||||
执行:blender --background --python edit.py
|
||||
它把一条剪辑计划翻译成 Blender 视频序列编辑器(VSE)的 API 调用序列。
|
||||
"""
|
||||
import os
|
||||
import bpy
|
||||
|
||||
SRC = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/source_cache/big-buck-bunny-trailer-480p.mov'
|
||||
OUT = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/preflight-reference.mp4'
|
||||
FPS = 25
|
||||
START = 9.0 # 目标片段起点(秒)
|
||||
END = 11.0 # 目标片段终点(秒)
|
||||
SUBTITLE = 'BIG BUNNY' # None 或字幕文本
|
||||
SLOWMO = 1.5 # None 或放慢倍率(factor>1 表示放慢 factor 倍)
|
||||
|
||||
scene = bpy.context.scene
|
||||
scene.render.fps = FPS
|
||||
scene.render.fps_base = 1.0
|
||||
scene.render.resolution_x = 854
|
||||
scene.render.resolution_y = 480
|
||||
scene.render.resolution_percentage = 100
|
||||
|
||||
# 清掉可能存在的旧序列,保证幂等
|
||||
if scene.sequence_editor:
|
||||
bpy.ops.sequencer.select_all(action='SELECT')
|
||||
bpy.ops.sequencer.delete()
|
||||
se = scene.sequence_editor_create()
|
||||
|
||||
start_frame = int(round(START * FPS))
|
||||
dur_frames = max(1, int(round((END - START) * FPS)))
|
||||
|
||||
# 1) 导入影片 + 音轨(new_sound 在无音轨素材上会抛 RuntimeError,忽略即可)
|
||||
movie = se.sequences.new_movie(name="clip", filepath=SRC, channel=1, frame_start=1 - start_frame)
|
||||
try:
|
||||
sound = se.sequences.new_sound(name="audio", filepath=SRC, channel=2, frame_start=1 - start_frame)
|
||||
except RuntimeError:
|
||||
sound = None
|
||||
|
||||
# 2) 裁剪 [START, END]:偏移掉片头,再固定成片时长
|
||||
for strip in (movie, sound):
|
||||
if strip is None:
|
||||
continue
|
||||
strip.frame_offset_start = start_frame
|
||||
strip.frame_final_duration = dur_frames
|
||||
|
||||
top_channel = 3
|
||||
|
||||
# 3) 慢动作:SPEED 特效条(MULTIPLY 模式,speed_factor = 1/倍率)
|
||||
if SLOWMO:
|
||||
speed = se.sequences.new_effect(
|
||||
name="slowmo", type='SPEED', channel=top_channel,
|
||||
frame_start=1, frame_end=1 + dur_frames, seq1=movie,
|
||||
)
|
||||
speed.use_default_fade = False
|
||||
speed.speed_control = 'MULTIPLY'
|
||||
speed.speed_factor = 1.0 / SLOWMO
|
||||
top_channel += 1
|
||||
# 放慢后成片总帧数按倍率拉长
|
||||
render_dur = int(round(dur_frames * SLOWMO))
|
||||
movie.frame_final_duration = render_dur
|
||||
else:
|
||||
render_dur = dur_frames
|
||||
|
||||
# 4) 字幕:TEXT 特效条,底部居中带半透明底框
|
||||
if SUBTITLE:
|
||||
txt = se.sequences.new_effect(
|
||||
name="subtitle", type='TEXT', channel=top_channel,
|
||||
frame_start=1, frame_end=1 + render_dur,
|
||||
)
|
||||
txt.text = SUBTITLE
|
||||
txt.font_size = 100
|
||||
txt.location = (0.5, 0.12)
|
||||
txt.align_x = 'CENTER'
|
||||
txt.align_y = 'BOTTOM'
|
||||
txt.use_box = True
|
||||
txt.box_color = (0.0, 0.0, 0.0, 0.6)
|
||||
|
||||
# 5) 渲染范围 + 输出为 mp4(H.264+AAC)
|
||||
scene.frame_start = 1
|
||||
scene.frame_end = render_dur
|
||||
|
||||
r = scene.render
|
||||
r.image_settings.file_format = 'FFMPEG'
|
||||
r.ffmpeg.format = 'MPEG4'
|
||||
r.ffmpeg.codec = 'H264'
|
||||
r.ffmpeg.audio_codec = 'AAC'
|
||||
r.filepath = OUT
|
||||
os.makedirs(os.path.dirname(OUT) or ".", exist_ok=True)
|
||||
|
||||
bpy.ops.render.render(animation=True)
|
||||
print("BLENDER_RENDER_DONE", OUT)
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"url": "https://download.blender.org/peach/trailer/trailer_480p.mov",
|
||||
"title": "Big Buck Bunny trailer (Blender Foundation Peach Open Movie Project)",
|
||||
"license": "Creative Commons Attribution 3.0",
|
||||
"license_url": "https://creativecommons.org/licenses/by/3.0/",
|
||||
"sha256": "36801b74638c12be9aa587e93cd18edfc9bc51a1c089ab2a19ee42beed9f497d",
|
||||
"probe": {
|
||||
"programs": [],
|
||||
"stream_groups": [],
|
||||
"streams": [
|
||||
{
|
||||
"index": 0,
|
||||
"codec_name": "h264",
|
||||
"codec_type": "video",
|
||||
"width": 853,
|
||||
"height": 480,
|
||||
"r_frame_rate": "25/1"
|
||||
},
|
||||
{
|
||||
"index": 1,
|
||||
"codec_name": "aac",
|
||||
"codec_type": "audio",
|
||||
"sample_rate": "48000",
|
||||
"channels": 6,
|
||||
"r_frame_rate": "0/0"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
|
||||
"duration": "32.995000",
|
||||
"size": "11061011"
|
||||
}
|
||||
},
|
||||
"naturally_occurring_scenes": true,
|
||||
"ground_truth": {
|
||||
"start": 9.08,
|
||||
"end": 11.2,
|
||||
"target": "the single continuous shot showing the large white rabbit walking alone in a sunny green meadow, after the ONE BIG RABBIT title and before the THREE RODENTS title",
|
||||
"method": "Human-labeled target shot bounded by ffmpeg scene-change frames; source inspection found transitions at 9.08 and 11.20 seconds.",
|
||||
"ffmpeg_scene_threshold": 0.35
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 258 KiB |
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"url": "https://download.blender.org/peach/trailer/trailer_480p.mov",
|
||||
"title": "Big Buck Bunny trailer (Blender Foundation Peach Open Movie Project)",
|
||||
"license": "Creative Commons Attribution 3.0",
|
||||
"license_url": "https://creativecommons.org/licenses/by/3.0/",
|
||||
"sha256": "36801b74638c12be9aa587e93cd18edfc9bc51a1c089ab2a19ee42beed9f497d",
|
||||
"probe": {
|
||||
"programs": [],
|
||||
"stream_groups": [],
|
||||
"streams": [
|
||||
{
|
||||
"index": 0,
|
||||
"codec_name": "h264",
|
||||
"codec_type": "video",
|
||||
"width": 853,
|
||||
"height": 480,
|
||||
"r_frame_rate": "25/1"
|
||||
},
|
||||
{
|
||||
"index": 1,
|
||||
"codec_name": "aac",
|
||||
"codec_type": "audio",
|
||||
"sample_rate": "48000",
|
||||
"channels": 6,
|
||||
"r_frame_rate": "0/0"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
|
||||
"duration": "32.995000",
|
||||
"size": "11061011"
|
||||
}
|
||||
},
|
||||
"naturally_occurring_scenes": true,
|
||||
"ground_truth": {
|
||||
"start": 9.08,
|
||||
"end": 11.2,
|
||||
"target": "the single continuous shot showing the large white rabbit walking alone in a sunny green meadow, after the ONE BIG RABBIT title and before the THREE RODENTS title",
|
||||
"method": "Human-labeled target shot bounded by ffmpeg scene-change frames; source inspection found transitions at 9.08 and 11.20 seconds.",
|
||||
"ffmpeg_scene_threshold": 0.35
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 258 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 382 KiB |
|
After Width: | Height: | Size: 440 KiB |
|
After Width: | Height: | Size: 440 KiB |
|
After Width: | Height: | Size: 192 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 330 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 179 KiB |
@@ -0,0 +1,186 @@
|
||||
{
|
||||
"request": "Cut out the shot of the large white rabbit walking alone in the sunny meadow, slow it to 1.5x duration, and add the subtitle BIG BUNNY along the bottom.",
|
||||
"target": "the single continuous shot showing the large white rabbit walking alone in a sunny green meadow, after the ONE BIG RABBIT title and before the THREE RODENTS title",
|
||||
"coarse_interval_s": 10,
|
||||
"coarse_frames": [
|
||||
{
|
||||
"timestamp_s": 0.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/coarse/frame-000.00.png",
|
||||
"sha256": "cdd5c7f27f84347a40eb467c356c5a2fda3facdad9057f246034e355b89dcfdd",
|
||||
"bytes": 1580
|
||||
},
|
||||
{
|
||||
"timestamp_s": 10.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/coarse/frame-010.00.png",
|
||||
"sha256": "bdf01683fab23e1e98099d0f6e19596eabcd96ddb1c643b3d0c6749b5f2995a9",
|
||||
"bytes": 288771
|
||||
},
|
||||
{
|
||||
"timestamp_s": 20.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/coarse/frame-020.00.png",
|
||||
"sha256": "713c2f7a5db41b01640dbae71ef4d5057c382dd1480d9e31bcc3f6d05c9da52b",
|
||||
"bytes": 183618
|
||||
},
|
||||
{
|
||||
"timestamp_s": 30.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/coarse/frame-030.00.png",
|
||||
"sha256": "ce5d5733e716607000f9d6aef75dbb9b31279dd50e7db7c6c1e714819624224a",
|
||||
"bytes": 264372
|
||||
},
|
||||
{
|
||||
"timestamp_s": 31.495,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/coarse/frame-031.50.png",
|
||||
"sha256": "57e555d305ac18228155454935f9a411a9e21ccc092348997f8e3299d4011b89",
|
||||
"bytes": 40146
|
||||
}
|
||||
],
|
||||
"coarse_result": {
|
||||
"start": 5.0,
|
||||
"end": 15.0,
|
||||
"reason": "The 10.00s frame shows the large white rabbit alone in a sunny green meadow with green grass, mountains, and clouds. The next frame at 20.00s features three rodents, indicating the rabbit shot ends before 20.00s. It starts after the 'ONE BIG RABBIT' title (before 10.00s), so the rough interval is 5.0-15.0s."
|
||||
},
|
||||
"fine_interval_s": 1,
|
||||
"fine_window": [
|
||||
0,
|
||||
20
|
||||
],
|
||||
"fine_frames": [
|
||||
{
|
||||
"timestamp_s": 0.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-000.00.png",
|
||||
"sha256": "cdd5c7f27f84347a40eb467c356c5a2fda3facdad9057f246034e355b89dcfdd",
|
||||
"bytes": 1580
|
||||
},
|
||||
{
|
||||
"timestamp_s": 1.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-001.00.png",
|
||||
"sha256": "702f6c8f994090d5f989709bea4372d9cfccb64ea4e09e8245639be85436ddc0",
|
||||
"bytes": 30336
|
||||
},
|
||||
{
|
||||
"timestamp_s": 2.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-002.00.png",
|
||||
"sha256": "0ad215be811389364b7616996f62082234c5759d2f5e489b50c2c794933dcb11",
|
||||
"bytes": 30702
|
||||
},
|
||||
{
|
||||
"timestamp_s": 3.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-003.00.png",
|
||||
"sha256": "ac7283cb0e9b36e87fffa5ef702b4ebc839c2cae9d68c2486ad6b7c6137281de",
|
||||
"bytes": 31566
|
||||
},
|
||||
{
|
||||
"timestamp_s": 4.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-004.00.png",
|
||||
"sha256": "83e61400d490cb6d008465e31f72466b14b8efbc25695003e571715a5ecf2609",
|
||||
"bytes": 391627
|
||||
},
|
||||
{
|
||||
"timestamp_s": 5.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-005.00.png",
|
||||
"sha256": "7bf0f2f437e8781ac96e6a27b41f975189c3784dbd3368672d43fd4b2d92813a",
|
||||
"bytes": 451029
|
||||
},
|
||||
{
|
||||
"timestamp_s": 6.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-006.00.png",
|
||||
"sha256": "618ee855deb607995c0be98d0a64db5614c4f851837af105e0672822947fe361",
|
||||
"bytes": 451002
|
||||
},
|
||||
{
|
||||
"timestamp_s": 7.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-007.00.png",
|
||||
"sha256": "40e9724ee1834abee7d12002cd83a4120738b0ffd0a294741c25c2135edb02b8",
|
||||
"bytes": 196294
|
||||
},
|
||||
{
|
||||
"timestamp_s": 8.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-008.00.png",
|
||||
"sha256": "1da6191f1a0c6ccc987a8e5d0682d7e664aa4ce8b8ce31d232bec5ae695b0c4e",
|
||||
"bytes": 25229
|
||||
},
|
||||
{
|
||||
"timestamp_s": 9.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-009.00.png",
|
||||
"sha256": "c0358569f2defb8cfdcd0c73393fc2e75cab6168920819a7c0d28395389132b7",
|
||||
"bytes": 26259
|
||||
},
|
||||
{
|
||||
"timestamp_s": 10.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-010.00.png",
|
||||
"sha256": "bdf01683fab23e1e98099d0f6e19596eabcd96ddb1c643b3d0c6749b5f2995a9",
|
||||
"bytes": 288771
|
||||
},
|
||||
{
|
||||
"timestamp_s": 11.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-011.00.png",
|
||||
"sha256": "c1abe47a8bd0e10472b75a472cea78ff24613c64ccc74ffba9b566d71336c4f4",
|
||||
"bytes": 290263
|
||||
},
|
||||
{
|
||||
"timestamp_s": 12.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-012.00.png",
|
||||
"sha256": "5833475f37ad6ccc7f98c953193368b11c4f3390d1633e224b0a43514c7aa2ec",
|
||||
"bytes": 23585
|
||||
},
|
||||
{
|
||||
"timestamp_s": 13.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-013.00.png",
|
||||
"sha256": "f14dca5370861a1b1f1ee95d1e00172314f27e60ec9f3451a16e08efb46cabf4",
|
||||
"bytes": 24310
|
||||
},
|
||||
{
|
||||
"timestamp_s": 14.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-014.00.png",
|
||||
"sha256": "ab5ed49e0a1267d80e53bc524db96a521aedf419d4a2e766463bd58fc2cbd96a",
|
||||
"bytes": 290328
|
||||
},
|
||||
{
|
||||
"timestamp_s": 15.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-015.00.png",
|
||||
"sha256": "101c7a220045bdad559ffabcf2345a307c4b2a8ace71c1f289f861cb5ac8dfcf",
|
||||
"bytes": 337454
|
||||
},
|
||||
{
|
||||
"timestamp_s": 16.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-016.00.png",
|
||||
"sha256": "6b674c7689ae86485ce112daa9a14cbd4334d3c41cbc12bcc8a06b0c34c3d0bd",
|
||||
"bytes": 118937
|
||||
},
|
||||
{
|
||||
"timestamp_s": 17.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-017.00.png",
|
||||
"sha256": "44134f20bffcd9fb57c3ca421a7be03fa2596962423a955140bf44e3d5c2582b",
|
||||
"bytes": 24201
|
||||
},
|
||||
{
|
||||
"timestamp_s": 18.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-018.00.png",
|
||||
"sha256": "bf44d8b974343063293c92d2933edd0e9a711802d44753f5c0c8b4f4cf3406aa",
|
||||
"bytes": 25412
|
||||
},
|
||||
{
|
||||
"timestamp_s": 19.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-019.00.png",
|
||||
"sha256": "7d2fdecd1cff9d025880e069d111c9e8aa0c488dd1e570b62f5147a136543271",
|
||||
"bytes": 78776
|
||||
},
|
||||
{
|
||||
"timestamp_s": 20.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/frames/fine/frame-020.00.png",
|
||||
"sha256": "713c2f7a5db41b01640dbae71ef4d5057c382dd1480d9e31bcc3f6d05c9da52b",
|
||||
"bytes": 183618
|
||||
}
|
||||
],
|
||||
"fine_result": {
|
||||
"start": 9.0,
|
||||
"end": 11.0,
|
||||
"reason": "Continuous shot of large white rabbit in sunny green meadow between 'ONE BIG RABBIT' title (ends at 8.00s) and 'THREE RODENTS' title (starts at 12.00s), visible in 10.00s and 11.00s samples."
|
||||
},
|
||||
"ground_truth": {
|
||||
"start": 9.08,
|
||||
"end": 11.2
|
||||
},
|
||||
"start_error_s": 0.08,
|
||||
"end_error_s": 0.2
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import bpy
|
||||
|
||||
# Clear default objects
|
||||
bpy.ops.object.select_all(action='SELECT')
|
||||
bpy.ops.object.delete()
|
||||
|
||||
# Set up scene and sequence editor
|
||||
scene = bpy.context.scene
|
||||
scene.sequence_editor = scene.sequence_editor_create()
|
||||
se = scene.sequence_editor
|
||||
|
||||
# File paths
|
||||
input_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/source.mov'
|
||||
output_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/negative_control.mp4'
|
||||
|
||||
# Video parameters
|
||||
source_fps = 25
|
||||
trim_start_sec = 0.0
|
||||
trim_end_sec = 3.0
|
||||
trim_duration_sec = trim_end_sec - trim_start_sec
|
||||
trim_duration_frames = int(trim_duration_sec * source_fps) # 75 frames
|
||||
output_duration_sec = trim_duration_sec * 1.5 # 4.5 seconds
|
||||
output_duration_frames = int(output_duration_sec * source_fps) # 113 frames (rounded up from 112.5)
|
||||
|
||||
speed_factor = trim_duration_sec / output_duration_sec # 0.666...
|
||||
|
||||
# Add video strip
|
||||
video_strip = se.sequences.new_movie(
|
||||
name='Video',
|
||||
filepath=input_path,
|
||||
channel=2,
|
||||
frame_start=1
|
||||
)
|
||||
video_strip.frame_offset_start = 0 # Start at 0s of source
|
||||
video_strip.frame_final_duration = trim_duration_frames # Trim to 3 seconds
|
||||
|
||||
# Add audio strip
|
||||
audio_strip = se.sequences.new_sound(
|
||||
name='Audio',
|
||||
filepath=input_path,
|
||||
channel=1,
|
||||
frame_start=1
|
||||
)
|
||||
audio_strip.frame_offset_start = 0
|
||||
audio_strip.frame_final_duration = trim_duration_frames
|
||||
|
||||
# Add speed effect to video
|
||||
speed_video = se.sequences.new_effect(
|
||||
name='Speed_Video',
|
||||
type='SPEED',
|
||||
channel=3,
|
||||
frame_start=1,
|
||||
seq1=video_strip
|
||||
)
|
||||
speed_video.speed_factor = speed_factor
|
||||
speed_video.frame_final_duration = output_duration_frames
|
||||
|
||||
# Add speed effect to audio
|
||||
speed_audio = se.sequences.new_effect(
|
||||
name='Speed_Audio',
|
||||
type='SPEED',
|
||||
channel=2,
|
||||
frame_start=1,
|
||||
seq1=audio_strip
|
||||
)
|
||||
speed_audio.speed_factor = speed_factor
|
||||
speed_audio.frame_final_duration = output_duration_frames
|
||||
|
||||
# Add subtitle text strip
|
||||
text_strip = se.sequences.new_effect(
|
||||
name='Subtitle',
|
||||
type='TEXT',
|
||||
channel=4,
|
||||
frame_start=1,
|
||||
frame_end=1 + output_duration_frames - 1
|
||||
)
|
||||
text_strip.text = 'BIG BUNNY'
|
||||
text_strip.align_x = 'CENTER'
|
||||
text_strip.align_y = 'BOTTOM'
|
||||
text_strip.font_size = 48
|
||||
text_strip.color = (1.0, 1.0, 1.0, 1.0) # White text
|
||||
|
||||
# Subtitle background box
|
||||
text_strip.use_box = True
|
||||
text_strip.box_color = (0.0, 0.0, 0.0, 0.5) # Semi-transparent black
|
||||
text_strip.box_margin_left = 10
|
||||
text_strip.box_margin_right = 10
|
||||
text_strip.box_margin_top = 10
|
||||
text_strip.box_margin_bottom = 10
|
||||
|
||||
# Render settings
|
||||
scene.render.resolution_x = 854
|
||||
scene.render.resolution_y = 480
|
||||
scene.render.resolution_percentage = 100
|
||||
scene.render.fps = source_fps
|
||||
scene.render.fps_base = 1.0
|
||||
|
||||
# Output format settings
|
||||
scene.render.image_settings.file_format = 'MPEG4'
|
||||
scene.render.ffmpeg.format = 'MPEG4'
|
||||
scene.render.ffmpeg.codec = 'H.264'
|
||||
scene.render.ffmpeg.audio_codec = 'AAC'
|
||||
scene.render.ffmpeg.audio_bitrate = 192
|
||||
scene.render.ffmpeg.constant_rate_factor = 'MEDIUM'
|
||||
scene.render.filepath = output_path
|
||||
|
||||
# Set scene frame range
|
||||
scene.frame_start = 1
|
||||
scene.frame_end = output_duration_frames
|
||||
|
||||
# Render animation
|
||||
bpy.ops.render.render(animation=True)
|
||||
@@ -0,0 +1,90 @@
|
||||
import bpy
|
||||
import math
|
||||
|
||||
# Clear default objects
|
||||
bpy.ops.object.select_all(action='SELECT')
|
||||
bpy.ops.object.delete()
|
||||
|
||||
# Set up scene
|
||||
scene = bpy.context.scene
|
||||
|
||||
# Render settings
|
||||
scene.render.resolution_x = 854
|
||||
scene.render.resolution_y = 480
|
||||
scene.render.resolution_percentage = 100
|
||||
scene.render.fps = 25
|
||||
scene.render.fps_base = 1.0
|
||||
scene.render.image_settings.file_format = 'MPEG4'
|
||||
scene.render.ffmpeg.codec = 'H264'
|
||||
scene.render.ffmpeg.audio_codec = 'AAC'
|
||||
scene.render.filepath = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/negative_control.mp4'
|
||||
|
||||
# Set up Video Sequence Editor
|
||||
if not scene.sequence_editor:
|
||||
scene.sequence_editor_create()
|
||||
scene.sequence_editor.sequences.clear()
|
||||
|
||||
# Import source movie
|
||||
input_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/source.mov'
|
||||
movie_strip = scene.sequence_editor.sequences.new_movie(
|
||||
name='Source',
|
||||
filepath=input_path,
|
||||
channel=1,
|
||||
frame_start=1
|
||||
)
|
||||
# Trim to 3 seconds (75 frames at 25fps)
|
||||
movie_strip.frame_final_duration = 75
|
||||
|
||||
# Add speed effect (1.5x duration = 2/3 speed)
|
||||
speed_strip = scene.sequence_editor.sequences.new_effect(
|
||||
name='Slow',
|
||||
type='SPEED',
|
||||
channel=2,
|
||||
frame_start=1,
|
||||
frame_end=movie_strip.frame_final_end,
|
||||
seq1=movie_strip
|
||||
)
|
||||
speed_strip.speed_factor = 2/3 # 3s * 1.5 = 4.5s duration
|
||||
|
||||
# Calculate scene frame range
|
||||
slowed_frames = movie_strip.frame_final_duration / speed_strip.speed_factor
|
||||
scene.frame_start = 1
|
||||
scene.frame_end = math.ceil(scene.frame_start + slowed_frames - 1)
|
||||
|
||||
# Create sequence editor if not exists
|
||||
if not scene.sequence_editor:
|
||||
scene.sequence_editor_create()
|
||||
|
||||
# Subtitle background (semi-transparent dark box)
|
||||
color_strip = scene.sequence_editor.sequences.new_effect(
|
||||
name='SubtitleBG',
|
||||
type='COLOR',
|
||||
channel=3,
|
||||
frame_start=scene.frame_start,
|
||||
frame_end=scene.frame_end
|
||||
)
|
||||
color_strip.color = (0.0, 0.0, 0.0) # Black
|
||||
color_strip.alpha = 0.5 # Semi-transparent
|
||||
color_strip.transform.scale_x = 0.4 # Box width
|
||||
color_strip.transform.scale_y = 0.15 # Box height
|
||||
color_strip.transform.translate_y = -0.4 # Bottom position
|
||||
color_strip.transform.align_x = 'CENTER' # Center horizontally
|
||||
|
||||
# Subtitle text
|
||||
text_strip = scene.sequence_editor.sequences.new_effect(
|
||||
name='SubtitleText',
|
||||
type='TEXT',
|
||||
channel=4,
|
||||
frame_start=scene.frame_start,
|
||||
frame_end=scene.frame_end
|
||||
)
|
||||
text_strip.text = 'BIG BUNNY'
|
||||
text_strip.align_x = 'CENTER'
|
||||
text_strip.align_y = 'CENTER'
|
||||
text_strip.font_size = 40
|
||||
text_strip.color = (1.0, 1.0, 1.0) # White text
|
||||
text_strip.transform.translate_y = -0.4 # Match background Y position
|
||||
text_strip.transform.align_x = 'CENTER'
|
||||
|
||||
# Render animation
|
||||
bpy.ops.render.render(animation=True)
|
||||
@@ -0,0 +1,73 @@
|
||||
import bpy
|
||||
|
||||
# Clear existing data to start fresh
|
||||
bpy.ops.wm.read_factory_settings(use_empty=True)
|
||||
|
||||
# Get the current scene
|
||||
scene = bpy.context.scene
|
||||
|
||||
# Set render resolution and FPS
|
||||
scene.render.resolution_x = 854
|
||||
scene.render.resolution_y = 480
|
||||
scene.render.resolution_percentage = 100
|
||||
scene.render.fps = 25
|
||||
scene.render.fps_base = 1.0
|
||||
|
||||
# Set render output settings
|
||||
scene.render.image_settings.file_format = 'FFMPEG'
|
||||
scene.render.ffmpeg.format = 'MPEG4'
|
||||
scene.render.ffmpeg.codec = 'H264'
|
||||
scene.render.ffmpeg.audio_codec = 'AAC'
|
||||
scene.render.ffmpeg.constant_rate_factor = 'MEDIUM'
|
||||
scene.render.filepath = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/negative_control.mp4'
|
||||
|
||||
# Create sequence editor
|
||||
scene.sequence_editor_create()
|
||||
seq_ed = scene.sequence_editor
|
||||
|
||||
# Input movie path
|
||||
input_movie = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-050817/source.mov'
|
||||
|
||||
# Add video strip with trim (0.000-3.000s = 0-75 frames at 25fps)
|
||||
video_strip = seq_ed.sequences.new_movie(name='Video', filepath=input_movie, channel=1, frame_start=0)
|
||||
video_strip.frame_offset_start = 0 # Start at source frame 0
|
||||
video_strip.frame_final_duration = 75 # 3s * 25fps = 75 frames
|
||||
|
||||
# Add speed effect to slow down (1.5x duration: 3s → 4.5s = 112.5 frames → 113 frames)
|
||||
speed_effect = seq_ed.sequences.new_effect(name='Speed', type='SPEED', channel=2, frame_start=0, frame_end=113, seq1=video_strip)
|
||||
speed_effect.speed_factor = 2/3 # Slows to 1.5x original duration
|
||||
|
||||
# Add audio strip from movie
|
||||
audio_strip = seq_ed.sequences.new_sound(name='Audio', filepath=input_movie, channel=1, frame_start=0)
|
||||
audio_strip.frame_offset_start = 0 # Match video trim start
|
||||
audio_strip.frame_final_duration = 75 # Match video trim duration
|
||||
|
||||
# Add speed effect to audio
|
||||
audio_speed = seq_ed.sequences.new_effect(name='AudioSpeed', type='SPEED', channel=2, frame_start=0, frame_end=113, seq1=audio_strip)
|
||||
audio_speed.speed_factor = 2/3
|
||||
audio_speed.use_audio = True
|
||||
|
||||
# Create subtitle background (semi-transparent dark box)
|
||||
bg_strip = seq_ed.sequences.new_effect(name='SubtitleBG', type='COLOR', channel=3, frame_start=0, frame_end=113)
|
||||
bg_strip.color = (0.1, 0.1, 0.1, 0.7) # Dark gray with 70% transparency
|
||||
bg_strip.align_x = 'CENTER'
|
||||
bg_strip.align_y = 'BOTTOM'
|
||||
bg_strip.transform.scale_x = 0.5 # Width of background box
|
||||
bg_strip.transform.scale_y = 0.15 # Height of background box
|
||||
bg_strip.transform.location_y = 0.03 # Position slightly above bottom edge
|
||||
|
||||
# Create subtitle text
|
||||
text_strip = seq_ed.sequences.new_effect(name='SubtitleText', type='TEXT', channel=4, frame_start=0, frame_end=113)
|
||||
text_strip.text = 'BIG BUNNY'
|
||||
text_strip.align_x = 'CENTER'
|
||||
text_strip.align_y = 'BOTTOM'
|
||||
text_strip.font_size = 48
|
||||
text_strip.color = (1.0, 1.0, 1.0) # White text
|
||||
text_strip.transform.location_y = 0.05 # Align with background box
|
||||
|
||||
# Set scene frame range to cover slowed duration (4.5 seconds = 112.5 frames → 113 frames)
|
||||
scene.frame_start = 0
|
||||
scene.frame_end = 113
|
||||
|
||||
# Render the animation
|
||||
bpy.ops.render.render(animation=True)
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"url": "https://download.blender.org/peach/trailer/trailer_480p.mov",
|
||||
"title": "Big Buck Bunny trailer (Blender Foundation Peach Open Movie Project)",
|
||||
"license": "Creative Commons Attribution 3.0",
|
||||
"license_url": "https://creativecommons.org/licenses/by/3.0/",
|
||||
"sha256": "36801b74638c12be9aa587e93cd18edfc9bc51a1c089ab2a19ee42beed9f497d",
|
||||
"probe": {
|
||||
"programs": [],
|
||||
"stream_groups": [],
|
||||
"streams": [
|
||||
{
|
||||
"index": 0,
|
||||
"codec_name": "h264",
|
||||
"codec_type": "video",
|
||||
"width": 853,
|
||||
"height": 480,
|
||||
"r_frame_rate": "25/1"
|
||||
},
|
||||
{
|
||||
"index": 1,
|
||||
"codec_name": "aac",
|
||||
"codec_type": "audio",
|
||||
"sample_rate": "48000",
|
||||
"channels": 6,
|
||||
"r_frame_rate": "0/0"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
|
||||
"duration": "32.995000",
|
||||
"size": "11061011"
|
||||
}
|
||||
},
|
||||
"naturally_occurring_scenes": true,
|
||||
"ground_truth": {
|
||||
"start": 9.08,
|
||||
"end": 11.2,
|
||||
"target": "the single continuous shot showing the large white rabbit walking alone in a sunny green meadow, after the ONE BIG RABBIT title and before the THREE RODENTS title",
|
||||
"method": "Human-labeled target shot bounded by ffmpeg scene-change frames; source inspection found transitions at 9.08 and 11.20 seconds.",
|
||||
"ffmpeg_scene_threshold": 0.35
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 258 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 440 KiB |
|
After Width: | Height: | Size: 440 KiB |
|
After Width: | Height: | Size: 192 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 330 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 188 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 206 KiB |
@@ -0,0 +1,186 @@
|
||||
{
|
||||
"request": "Cut out the shot of the large white rabbit walking alone in the sunny meadow, slow it to 1.5x duration, and add the subtitle BIG BUNNY along the bottom.",
|
||||
"target": "the single continuous shot showing the large white rabbit walking alone in a sunny green meadow, after the ONE BIG RABBIT title and before the THREE RODENTS title",
|
||||
"coarse_interval_s": 10,
|
||||
"coarse_frames": [
|
||||
{
|
||||
"timestamp_s": 0.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/coarse/frame-000.00.png",
|
||||
"sha256": "cdd5c7f27f84347a40eb467c356c5a2fda3facdad9057f246034e355b89dcfdd",
|
||||
"bytes": 1580
|
||||
},
|
||||
{
|
||||
"timestamp_s": 10.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/coarse/frame-010.00.png",
|
||||
"sha256": "bdf01683fab23e1e98099d0f6e19596eabcd96ddb1c643b3d0c6749b5f2995a9",
|
||||
"bytes": 288771
|
||||
},
|
||||
{
|
||||
"timestamp_s": 20.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/coarse/frame-020.00.png",
|
||||
"sha256": "713c2f7a5db41b01640dbae71ef4d5057c382dd1480d9e31bcc3f6d05c9da52b",
|
||||
"bytes": 183618
|
||||
},
|
||||
{
|
||||
"timestamp_s": 30.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/coarse/frame-030.00.png",
|
||||
"sha256": "ce5d5733e716607000f9d6aef75dbb9b31279dd50e7db7c6c1e714819624224a",
|
||||
"bytes": 264372
|
||||
},
|
||||
{
|
||||
"timestamp_s": 31.495,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/coarse/frame-031.50.png",
|
||||
"sha256": "57e555d305ac18228155454935f9a411a9e21ccc092348997f8e3299d4011b89",
|
||||
"bytes": 40146
|
||||
}
|
||||
],
|
||||
"coarse_result": {
|
||||
"start": 10.0,
|
||||
"end": 20.0,
|
||||
"reason": "The 10.00s frame shows the large white rabbit standing alone in a sunny green meadow with rolling hills and a clear sky, matching the target description. The next frame at 20.00s transitions to three rodents in a darker forested area (likely the 'THREE RODENTS' title content), indicating the rabbit shot is continuous between these timestamps."
|
||||
},
|
||||
"fine_interval_s": 1,
|
||||
"fine_window": [
|
||||
5,
|
||||
25
|
||||
],
|
||||
"fine_frames": [
|
||||
{
|
||||
"timestamp_s": 5.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-005.00.png",
|
||||
"sha256": "7bf0f2f437e8781ac96e6a27b41f975189c3784dbd3368672d43fd4b2d92813a",
|
||||
"bytes": 451029
|
||||
},
|
||||
{
|
||||
"timestamp_s": 6.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-006.00.png",
|
||||
"sha256": "618ee855deb607995c0be98d0a64db5614c4f851837af105e0672822947fe361",
|
||||
"bytes": 451002
|
||||
},
|
||||
{
|
||||
"timestamp_s": 7.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-007.00.png",
|
||||
"sha256": "40e9724ee1834abee7d12002cd83a4120738b0ffd0a294741c25c2135edb02b8",
|
||||
"bytes": 196294
|
||||
},
|
||||
{
|
||||
"timestamp_s": 8.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-008.00.png",
|
||||
"sha256": "1da6191f1a0c6ccc987a8e5d0682d7e664aa4ce8b8ce31d232bec5ae695b0c4e",
|
||||
"bytes": 25229
|
||||
},
|
||||
{
|
||||
"timestamp_s": 9.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-009.00.png",
|
||||
"sha256": "c0358569f2defb8cfdcd0c73393fc2e75cab6168920819a7c0d28395389132b7",
|
||||
"bytes": 26259
|
||||
},
|
||||
{
|
||||
"timestamp_s": 10.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-010.00.png",
|
||||
"sha256": "bdf01683fab23e1e98099d0f6e19596eabcd96ddb1c643b3d0c6749b5f2995a9",
|
||||
"bytes": 288771
|
||||
},
|
||||
{
|
||||
"timestamp_s": 11.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-011.00.png",
|
||||
"sha256": "c1abe47a8bd0e10472b75a472cea78ff24613c64ccc74ffba9b566d71336c4f4",
|
||||
"bytes": 290263
|
||||
},
|
||||
{
|
||||
"timestamp_s": 12.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-012.00.png",
|
||||
"sha256": "5833475f37ad6ccc7f98c953193368b11c4f3390d1633e224b0a43514c7aa2ec",
|
||||
"bytes": 23585
|
||||
},
|
||||
{
|
||||
"timestamp_s": 13.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-013.00.png",
|
||||
"sha256": "f14dca5370861a1b1f1ee95d1e00172314f27e60ec9f3451a16e08efb46cabf4",
|
||||
"bytes": 24310
|
||||
},
|
||||
{
|
||||
"timestamp_s": 14.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-014.00.png",
|
||||
"sha256": "ab5ed49e0a1267d80e53bc524db96a521aedf419d4a2e766463bd58fc2cbd96a",
|
||||
"bytes": 290328
|
||||
},
|
||||
{
|
||||
"timestamp_s": 15.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-015.00.png",
|
||||
"sha256": "101c7a220045bdad559ffabcf2345a307c4b2a8ace71c1f289f861cb5ac8dfcf",
|
||||
"bytes": 337454
|
||||
},
|
||||
{
|
||||
"timestamp_s": 16.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-016.00.png",
|
||||
"sha256": "6b674c7689ae86485ce112daa9a14cbd4334d3c41cbc12bcc8a06b0c34c3d0bd",
|
||||
"bytes": 118937
|
||||
},
|
||||
{
|
||||
"timestamp_s": 17.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-017.00.png",
|
||||
"sha256": "44134f20bffcd9fb57c3ca421a7be03fa2596962423a955140bf44e3d5c2582b",
|
||||
"bytes": 24201
|
||||
},
|
||||
{
|
||||
"timestamp_s": 18.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-018.00.png",
|
||||
"sha256": "bf44d8b974343063293c92d2933edd0e9a711802d44753f5c0c8b4f4cf3406aa",
|
||||
"bytes": 25412
|
||||
},
|
||||
{
|
||||
"timestamp_s": 19.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-019.00.png",
|
||||
"sha256": "7d2fdecd1cff9d025880e069d111c9e8aa0c488dd1e570b62f5147a136543271",
|
||||
"bytes": 78776
|
||||
},
|
||||
{
|
||||
"timestamp_s": 20.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-020.00.png",
|
||||
"sha256": "713c2f7a5db41b01640dbae71ef4d5057c382dd1480d9e31bcc3f6d05c9da52b",
|
||||
"bytes": 183618
|
||||
},
|
||||
{
|
||||
"timestamp_s": 21.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-021.00.png",
|
||||
"sha256": "c9758159919eb5f8612e3af01258d1c7792d446ca5c08add2ff3dcd3b97e7617",
|
||||
"bytes": 96371
|
||||
},
|
||||
{
|
||||
"timestamp_s": 22.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-022.00.png",
|
||||
"sha256": "54b41278b256654341515bee8f7adb3166bdb15c90f3da9f7f47eb72cad77d33",
|
||||
"bytes": 192864
|
||||
},
|
||||
{
|
||||
"timestamp_s": 23.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-023.00.png",
|
||||
"sha256": "3e49ae19ac287a5acdcff0db46d93d3ca77f98d039d9c53f07210466a323b5b3",
|
||||
"bytes": 22428
|
||||
},
|
||||
{
|
||||
"timestamp_s": 24.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-024.00.png",
|
||||
"sha256": "6eb1ae362db441052be6685922270fcd86572c8b223e99a41a519424ac113c0d",
|
||||
"bytes": 24410
|
||||
},
|
||||
{
|
||||
"timestamp_s": 25.0,
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-025.00.png",
|
||||
"sha256": "354595be0073fcaed614da1ff41177f01e54f74b63f5614ed5033a9c00e0a773",
|
||||
"bytes": 211411
|
||||
}
|
||||
],
|
||||
"fine_result": {
|
||||
"start": 9.0,
|
||||
"end": 12.0,
|
||||
"reason": "Starts immediately after the 'ONE BIG RABBIT' title (ends at 9.00s) and ends just before the 'THREE RODENTS' title (starts at 12.00s), with continuous visuals of the large white rabbit in the sunny green meadow at 10.00s and 11.00s."
|
||||
},
|
||||
"ground_truth": {
|
||||
"start": 9.08,
|
||||
"end": 11.2
|
||||
},
|
||||
"start_error_s": 0.08,
|
||||
"end_error_s": 0.8
|
||||
}
|
||||
@@ -0,0 +1,546 @@
|
||||
{
|
||||
"calls": [
|
||||
{
|
||||
"purpose": "coarse_10_second_visual_localization",
|
||||
"provider": "ark",
|
||||
"endpoint": "https://ark.cn-beijing.volces.com/api/v3",
|
||||
"request": {
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "These are frames from one contiguous real trailer sampled about every 10 seconds.\nLocate this target: the single continuous shot showing the large white rabbit walking alone in a sunny green meadow, after the ONE BIG RABBIT title and before the THREE RODENTS title.\nReturn JSON {\"start\":seconds,\"end\":seconds,\"reason\":\"visual evidence\"} with a rough continuous interval. Use timestamps and visual content only."
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=0.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/coarse/frame-000.00.png",
|
||||
"sha256": "cdd5c7f27f84347a40eb467c356c5a2fda3facdad9057f246034e355b89dcfdd",
|
||||
"bytes": 1580
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=10.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/coarse/frame-010.00.png",
|
||||
"sha256": "bdf01683fab23e1e98099d0f6e19596eabcd96ddb1c643b3d0c6749b5f2995a9",
|
||||
"bytes": 288771
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=20.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/coarse/frame-020.00.png",
|
||||
"sha256": "713c2f7a5db41b01640dbae71ef4d5057c382dd1480d9e31bcc3f6d05c9da52b",
|
||||
"bytes": 183618
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=30.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/coarse/frame-030.00.png",
|
||||
"sha256": "ce5d5733e716607000f9d6aef75dbb9b31279dd50e7db7c6c1e714819624224a",
|
||||
"bytes": 264372
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=31.50s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/coarse/frame-031.50.png",
|
||||
"sha256": "57e555d305ac18228155454935f9a411a9e21ccc092348997f8e3299d4011b89",
|
||||
"bytes": 40146
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"temperature": 0,
|
||||
"max_tokens": 700,
|
||||
"response_format": {
|
||||
"type": "json_object"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"id": "02178536012758415b00b15f7b15a122bee0bef9a71075862cfbb",
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"finish_reason": "stop",
|
||||
"content": "{\"start\":10.00,\"end\":20.00,\"reason\":\"The 10.00s frame shows the large white rabbit standing alone in a sunny green meadow with rolling hills and a clear sky, matching the target description. The next frame at 20.00s transitions to three rodents in a darker forested area (likely the 'THREE RODENTS' title content), indicating the rabbit shot is continuous between these timestamps.\"}"
|
||||
},
|
||||
"usage": {
|
||||
"prompt_tokens": 1686,
|
||||
"completion_tokens": 734,
|
||||
"total_tokens": 2420
|
||||
},
|
||||
"latency_s": 20.057
|
||||
},
|
||||
{
|
||||
"purpose": "fine_1_second_visual_localization",
|
||||
"provider": "ark",
|
||||
"endpoint": "https://ark.cn-beijing.volces.com/api/v3",
|
||||
"request": {
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "These are one-second samples from the narrowed window [5.0, 25.0] seconds of the same real trailer.\nPrecisely locate the boundaries of this one continuous target shot: the single continuous shot showing the large white rabbit walking alone in a sunny green meadow, after the ONE BIG RABBIT title and before the THREE RODENTS title.\nReturn JSON {\"start\":seconds,\"end\":seconds,\"reason\":\"visual boundary evidence\"}. The answer may interpolate between adjacent one-second samples; do not include either neighboring title card."
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=5.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-005.00.png",
|
||||
"sha256": "7bf0f2f437e8781ac96e6a27b41f975189c3784dbd3368672d43fd4b2d92813a",
|
||||
"bytes": 451029
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=6.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-006.00.png",
|
||||
"sha256": "618ee855deb607995c0be98d0a64db5614c4f851837af105e0672822947fe361",
|
||||
"bytes": 451002
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=7.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-007.00.png",
|
||||
"sha256": "40e9724ee1834abee7d12002cd83a4120738b0ffd0a294741c25c2135edb02b8",
|
||||
"bytes": 196294
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=8.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-008.00.png",
|
||||
"sha256": "1da6191f1a0c6ccc987a8e5d0682d7e664aa4ce8b8ce31d232bec5ae695b0c4e",
|
||||
"bytes": 25229
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=9.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-009.00.png",
|
||||
"sha256": "c0358569f2defb8cfdcd0c73393fc2e75cab6168920819a7c0d28395389132b7",
|
||||
"bytes": 26259
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=10.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-010.00.png",
|
||||
"sha256": "bdf01683fab23e1e98099d0f6e19596eabcd96ddb1c643b3d0c6749b5f2995a9",
|
||||
"bytes": 288771
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=11.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-011.00.png",
|
||||
"sha256": "c1abe47a8bd0e10472b75a472cea78ff24613c64ccc74ffba9b566d71336c4f4",
|
||||
"bytes": 290263
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=12.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-012.00.png",
|
||||
"sha256": "5833475f37ad6ccc7f98c953193368b11c4f3390d1633e224b0a43514c7aa2ec",
|
||||
"bytes": 23585
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=13.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-013.00.png",
|
||||
"sha256": "f14dca5370861a1b1f1ee95d1e00172314f27e60ec9f3451a16e08efb46cabf4",
|
||||
"bytes": 24310
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=14.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-014.00.png",
|
||||
"sha256": "ab5ed49e0a1267d80e53bc524db96a521aedf419d4a2e766463bd58fc2cbd96a",
|
||||
"bytes": 290328
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=15.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-015.00.png",
|
||||
"sha256": "101c7a220045bdad559ffabcf2345a307c4b2a8ace71c1f289f861cb5ac8dfcf",
|
||||
"bytes": 337454
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=16.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-016.00.png",
|
||||
"sha256": "6b674c7689ae86485ce112daa9a14cbd4334d3c41cbc12bcc8a06b0c34c3d0bd",
|
||||
"bytes": 118937
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=17.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-017.00.png",
|
||||
"sha256": "44134f20bffcd9fb57c3ca421a7be03fa2596962423a955140bf44e3d5c2582b",
|
||||
"bytes": 24201
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=18.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-018.00.png",
|
||||
"sha256": "bf44d8b974343063293c92d2933edd0e9a711802d44753f5c0c8b4f4cf3406aa",
|
||||
"bytes": 25412
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=19.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-019.00.png",
|
||||
"sha256": "7d2fdecd1cff9d025880e069d111c9e8aa0c488dd1e570b62f5147a136543271",
|
||||
"bytes": 78776
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=20.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-020.00.png",
|
||||
"sha256": "713c2f7a5db41b01640dbae71ef4d5057c382dd1480d9e31bcc3f6d05c9da52b",
|
||||
"bytes": 183618
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=21.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-021.00.png",
|
||||
"sha256": "c9758159919eb5f8612e3af01258d1c7792d446ca5c08add2ff3dcd3b97e7617",
|
||||
"bytes": 96371
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=22.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-022.00.png",
|
||||
"sha256": "54b41278b256654341515bee8f7adb3166bdb15c90f3da9f7f47eb72cad77d33",
|
||||
"bytes": 192864
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=23.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-023.00.png",
|
||||
"sha256": "3e49ae19ac287a5acdcff0db46d93d3ca77f98d039d9c53f07210466a323b5b3",
|
||||
"bytes": 22428
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=24.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-024.00.png",
|
||||
"sha256": "6eb1ae362db441052be6685922270fcd86572c8b223e99a41a519424ac113c0d",
|
||||
"bytes": 24410
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": "timestamp=25.00s"
|
||||
},
|
||||
{
|
||||
"type": "image_artifact",
|
||||
"path": "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/frames/fine/frame-025.00.png",
|
||||
"sha256": "354595be0073fcaed614da1ff41177f01e54f74b63f5614ed5033a9c00e0a773",
|
||||
"bytes": 211411
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"temperature": 0,
|
||||
"max_tokens": 700,
|
||||
"response_format": {
|
||||
"type": "json_object"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"id": "02178536014931215b00b15f7b15a122bee0bef9a7107589f12c6",
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"finish_reason": "stop",
|
||||
"content": "{\"start\":9.0,\"end\":12.0,\"reason\":\"Starts immediately after the 'ONE BIG RABBIT' title (ends at 9.00s) and ends just before the 'THREE RODENTS' title (starts at 12.00s), with continuous visuals of the large white rabbit in the sunny green meadow at 10.00s and 11.00s.\"}"
|
||||
},
|
||||
"usage": {
|
||||
"prompt_tokens": 6555,
|
||||
"completion_tokens": 1158,
|
||||
"total_tokens": 7713
|
||||
},
|
||||
"latency_s": 31.727
|
||||
},
|
||||
{
|
||||
"purpose": "blender_script_negative-control_attempt_1",
|
||||
"provider": "ark",
|
||||
"endpoint": "https://ark.cn-beijing.volces.com/api/v3",
|
||||
"request": {
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a Blender VSE engineer. Return one JSON object only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate a complete Blender 4.3 Python script for this video edit.\n\nInput movie: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov\nOutput MP4: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4\nSource FPS: 25\nSource size: 853x480; render at 854x480 (one-pixel even-width pad required by H.264)\nTrim interval: [0.000, 3.000] seconds\nEffects: slow playback so output duration is 1.5 times the trimmed interval; add bottom-centered subtitle BIG BUNNY with a visible semi-transparent dark box.\n\nRequirements:\n- Use bpy and Blender's Video Sequence Editor, including new_movie, new_sound when available, frame_offset_start/frame_final_duration, a SPEED effect, and a TEXT effect.\n- Render exactly 854x480 at 25 fps through Blender to MPEG-4 H.264 with AAC audio.\n- Set the scene frame range to the slowed duration and call bpy.ops.render.render(animation=True).\n- Create only the requested output. Do not invoke ffmpeg, subprocesses, a shell, the network, or read credentials.\n- Use APIs available in Blender 4.3 (scene.sequence_editor_create().sequences).\n- In Blender 4.3, SpeedControlSequence has no use_audio property. Never read or assign use_audio, and do not apply a SPEED effect to the sound strip. A valid movie slow-motion pattern is speed_control='MULTIPLY', speed_factor=1/1.5, and extending the movie/render duration; the sound strip may remain normally trimmed.\n- For the subtitle background, prefer the TEXT strip's use_box=True and box_color=(0,0,0,0.6); do not assume a COLOR strip has text-layout properties.\n\nReturn one JSON object only: {\"code\":\"complete executable Python source\"}.\n"
|
||||
}
|
||||
],
|
||||
"temperature": 0,
|
||||
"max_tokens": 7000,
|
||||
"response_format": {
|
||||
"type": "json_object"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"id": "02178536018101615b00b15f7b15a122bee0bef9a710758b49a93",
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"finish_reason": "stop",
|
||||
"content": "{\"code\":\"import bpy\\n\\n# Clear existing objects to start fresh\\nbpy.ops.object.select_all(action='SELECT')\\nbpy.ops.object.delete()\\n\\n# Configuration paths and parameters\\nINPUT_MOVIE = \\\"/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov\\\"\\nOUTPUT_MP4 = \\\"/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4\\\"\\nSOURCE_FPS = 25\\nTRIM_DURATION_SECONDS = 3.0\\nSLOW_FACTOR = 1.5\\nRENDER_RESOLUTION = (854, 480)\\n\\n# Calculate frame values\\ntrim_frames = int(TRIM_DURATION_SECONDS * SOURCE_FPS)\\nslowed_frames = int(trim_frames * SLOW_FACTOR)\\nscene = bpy.context.scene\\n\\n# Create sequence editor\\nseq_ed = scene.sequence_editor_create()\\n\\n# Add movie strip with trim\\nmovie_strip = seq_ed.sequences.new_movie(\\n name=\\\"SourceVideo\\\",\\n filepath=INPUT_MOVIE,\\n channel=1,\\n frame_start=1\\n)\\nmovie_strip.frame_offset_start = 0 # Start at beginning of source\\nmovie_strip.frame_final_duration = trim_frames # Trim to 3 seconds\\n\\n# Locate and trim audio strip (auto-created with movie)\\nsound_strip = None\\nfor strip in seq_ed.sequences:\\n if strip.type == 'SOUND' and strip.channel == 2 and strip.frame_start == 1:\\n sound_strip = strip\\nif sound_strip:\\n sound_strip.frame_final_duration = trim_frames # Keep audio at original speed\\n\\n# Add speed effect to video (slow motion)\\nspeed_strip = seq_ed.sequences.new_effect(\\n name=\\\"SlowMotion\\\",\\n type='SPEED',\\n channel=3,\\n frame_start=1,\\n frame_end=1 + slowed_frames - 1,\\n target=movie_strip\\n)\\nspeed_strip.speed_control = 'MULTIPLY'\\nspeed_strip.speed_factor = 1 / SLOW_FACTOR # 1/1.5 speed factor\\n\\n# Add subtitle text strip with background box\\ntext_strip = seq_ed.sequences.new_text(\\n name=\\\"Subtitle\\\",\\n text=\\\"BIG BUNNY\\\",\\n channel=4,\\n frame_start=1,\\n frame_end=1 + slowed_frames - 1\\n)\\ntext_strip.align_x = 'CENTER'\\ntext_strip.align_y = 'BOTTOM'\\ntext_strip.use_box = True\\ntext_strip.box_color = (0.0, 0.0, 0.0, 0.6) # Black semi-transparent box\\ntext_strip.font_size = 48 # Visible size for 854x480 resolution\\n\\n# Configure render settings\\nscene.render.resolution_x = RENDER_RESOLUTION[0]\\nscene.render.resolution_y = RENDER_RESOLUTION[1]\\nscene.render.resolution_percentage = 100\\nscene.render.fps = SOURCE_FPS\\nscene.render.fps_base = 1.0\\nscene.render.image_settings.file_format = 'FFMPEG'\\nscene.render.ffmpeg.format = 'MPEG4'\\nscene.render.ffmpeg.codec = 'H264'\\nscene.render.ffmpeg.audio_codec = 'AAC'\\nscene.render.filepath = OUTPUT_MP4\\n\\n# Set render frame range\\nscene.frame_start = 1\\nscene.frame_end = 1 + slowed_frames - 1\\n\\n# Execute render\\nbpy.ops.render.render(animation=True)\"}"
|
||||
},
|
||||
"usage": {
|
||||
"prompt_tokens": 614,
|
||||
"completion_tokens": 6404,
|
||||
"total_tokens": 7018
|
||||
},
|
||||
"latency_s": 153.914
|
||||
},
|
||||
{
|
||||
"purpose": "blender_script_negative-control_attempt_2",
|
||||
"provider": "ark",
|
||||
"endpoint": "https://ark.cn-beijing.volces.com/api/v3",
|
||||
"request": {
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a Blender VSE engineer. Return one JSON object only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate a complete Blender 4.3 Python script for this video edit.\n\nInput movie: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov\nOutput MP4: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4\nSource FPS: 25\nSource size: 853x480; render at 854x480 (one-pixel even-width pad required by H.264)\nTrim interval: [0.000, 3.000] seconds\nEffects: slow playback so output duration is 1.5 times the trimmed interval; add bottom-centered subtitle BIG BUNNY with a visible semi-transparent dark box.\n\nRequirements:\n- Use bpy and Blender's Video Sequence Editor, including new_movie, new_sound when available, frame_offset_start/frame_final_duration, a SPEED effect, and a TEXT effect.\n- Render exactly 854x480 at 25 fps through Blender to MPEG-4 H.264 with AAC audio.\n- Set the scene frame range to the slowed duration and call bpy.ops.render.render(animation=True).\n- Create only the requested output. Do not invoke ffmpeg, subprocesses, a shell, the network, or read credentials.\n- Use APIs available in Blender 4.3 (scene.sequence_editor_create().sequences).\n- In Blender 4.3, SpeedControlSequence has no use_audio property. Never read or assign use_audio, and do not apply a SPEED effect to the sound strip. A valid movie slow-motion pattern is speed_control='MULTIPLY', speed_factor=1/1.5, and extending the movie/render duration; the sound strip may remain normally trimmed.\n- For the subtitle background, prefer the TEXT strip's use_box=True and box_color=(0,0,0,0.6); do not assume a COLOR strip has text-layout properties.\n\nReturn one JSON object only: {\"code\":\"complete executable Python source\"}.\n\nPrior executable feedback:\nStatic safety/API validation failed: ValueError: generated script omits requested Blender API operations: ['TEXT']"
|
||||
}
|
||||
],
|
||||
"temperature": 0,
|
||||
"max_tokens": 7000,
|
||||
"response_format": {
|
||||
"type": "json_object"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"id": "02178536033493315b00b15f7b15a122bee0bef9a710758de0884",
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"finish_reason": "stop",
|
||||
"content": "{\"code\":\"import bpy\\n\\n# Clear existing data\\nbpy.ops.wm.read_factory_settings(use_empty=True)\\nscene = bpy.context.scene\\n\\n# Scene settings\\nscene.render.resolution_x = 854\\nscene.render.resolution_y = 480\\nscene.render.resolution_percentage = 100\\nscene.render.fps = 25\\nscene.render.fps_base = 1.0\\n\\n# Create sequence editor\\nif not scene.sequence_editor:\\n scene.sequence_editor_create()\\nseq_ed = scene.sequence_editor\\nsequences = seq_ed.sequences\\n\\n# File paths\\ninput_movie = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov'\\noutput_mp4 = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4'\\n\\n# Add movie strip (3 seconds = 75 frames at 25fps)\\nmov_strip = sequences.new_movie(\\n name='SourceMovie',\\n filepath=input_movie,\\n frame_start=1,\\n channel=1\\n)\\nmov_strip.frame_offset_start = 0\\nmov_strip.frame_final_duration = 75 # 3s * 25fps\\n\\n# Locate and trim sound strip\\nsound_strip = next((s for s in sequences if s.type == 'SOUND' and s.frame_start == mov_strip.frame_start), None)\\nif sound_strip:\\n sound_strip.frame_final_duration = 75 # Keep original audio duration\\n\\n# Add speed effect (1.5x slowdown)\\nspeed_strip = sequences.new_effect(\\n name='SlowMotion',\\n type='SPEED',\\n frame_start=1,\\n channel=2,\\n input_1=mov_strip\\n)\\nspeed_strip.speed_control = 'MULTIPLY'\\nspeed_strip.speed_factor = 1 / 1.5\\n\\n# Calculate slowed duration (4.5s = 112.5 frames → 113 frames)\\nslowed_frames = int(4.5 * 25) + 1\\nscene.frame_start = 1\\nscene.frame_end = slowed_frames\\n\\n# Add subtitle text strip\\ntext_strip = sequences.new_effect(\\n name='Subtitle',\\n type='TEXT',\\n frame_start=1,\\n frame_end=scene.frame_end,\\n channel=3\\n)\\ntext_strip.text = 'BIG BUNNY'\\ntext_strip.align_x = 'CENTER'\\ntext_strip.align_y = 'BOTTOM'\\ntext_strip.use_box = True\\ntext_strip.box_color = (0, 0, 0, 0.6)\\ntext_strip.font_size = 48\\n\\n# Render settings\\nscene.render.filepath = output_mp4\\nscene.render.image_settings.file_format = 'FFMPEG'\\nscene.render.ffmpeg.format = 'MPEG4'\\nscene.render.ffmpeg.codec = 'H264'\\nscene.render.ffmpeg.audio_codec = 'AAC'\\nscene.render.ffmpeg.constant_rate_factor = 'MEDIUM'\\n\\n# Render animation\\nbpy.ops.render.render(animation=True)\"}"
|
||||
},
|
||||
"usage": {
|
||||
"prompt_tokens": 641,
|
||||
"completion_tokens": 4682,
|
||||
"total_tokens": 5323
|
||||
},
|
||||
"latency_s": 103.993
|
||||
},
|
||||
{
|
||||
"purpose": "blender_script_negative-control_attempt_3",
|
||||
"provider": "ark",
|
||||
"endpoint": "https://ark.cn-beijing.volces.com/api/v3",
|
||||
"request": {
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a Blender VSE engineer. Return one JSON object only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate a complete Blender 4.3 Python script for this video edit.\n\nInput movie: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov\nOutput MP4: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4\nSource FPS: 25\nSource size: 853x480; render at 854x480 (one-pixel even-width pad required by H.264)\nTrim interval: [0.000, 3.000] seconds\nEffects: slow playback so output duration is 1.5 times the trimmed interval; add bottom-centered subtitle BIG BUNNY with a visible semi-transparent dark box.\n\nRequirements:\n- Use bpy and Blender's Video Sequence Editor, including new_movie, new_sound when available, frame_offset_start/frame_final_duration, a SPEED effect, and a TEXT effect.\n- Render exactly 854x480 at 25 fps through Blender to MPEG-4 H.264 with AAC audio.\n- Set the scene frame range to the slowed duration and call bpy.ops.render.render(animation=True).\n- Create only the requested output. Do not invoke ffmpeg, subprocesses, a shell, the network, or read credentials.\n- Use APIs available in Blender 4.3 (scene.sequence_editor_create().sequences).\n- In Blender 4.3, SpeedControlSequence has no use_audio property. Never read or assign use_audio, and do not apply a SPEED effect to the sound strip. A valid movie slow-motion pattern is speed_control='MULTIPLY', speed_factor=1/1.5, and extending the movie/render duration; the sound strip may remain normally trimmed.\n- For the subtitle background, prefer the TEXT strip's use_box=True and box_color=(0,0,0,0.6); do not assume a COLOR strip has text-layout properties.\n\nReturn one JSON object only: {\"code\":\"complete executable Python source\"}.\n\nPrior executable feedback:\nBlender exit=0; output_exists=False. Tail of real Blender log:\nBlender 4.3.2 (hash 32f5fdce0a0a built 2024-12-17 02:14:25)\nTraceback (most recent call last):\n File \"/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/scripts/negative-control-attempt-2.py\", line 40, in <module>\n speed_strip = sequences.new_effect(\n ^^^^^^^^^^^^^^^^^^^^^\nTypeError: SequencesTopLevel.new_effect(): was called with invalid keyword argument(s) (input_1), expected (name, type, channel, frame_start, frame_end, seq1, seq2)\n\nBlender quit"
|
||||
}
|
||||
],
|
||||
"temperature": 0,
|
||||
"max_tokens": 7000,
|
||||
"response_format": {
|
||||
"type": "json_object"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"id": "02178536043966315b00b15f7b15a122bee0bef9a710758ef6add",
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"finish_reason": "stop",
|
||||
"content": "{\"code\":\"import bpy\\nimport os\\n\\n# Clear default objects\\nbpy.ops.object.select_all(action='SELECT')\\nbpy.ops.object.delete()\\n\\n# Set up scene\\nscene = bpy.context.scene\\nscene.render.fps = 25\\nscene.render.fps_base = 1.0\\nscene.render.resolution_x = 854\\nscene.render.resolution_y = 480\\nscene.render.resolution_percentage = 100\\n\\n# Configure output settings\\nscene.render.image_settings.file_format = 'FFMPEG'\\nscene.render.ffmpeg.format = 'MPEG4'\\nscene.render.ffmpeg.codec = 'H264'\\nscene.render.ffmpeg.audio_codec = 'AAC'\\nscene.render.ffmpeg.audio_bitrate = 192\\noutput_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4'\\nscene.render.filepath = output_path\\n\\n# Create sequence editor\\nscene.sequence_editor_create()\\nsequences = scene.sequence_editor.sequences\\n\\n# Import source movie and sound\\nsource_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov'\\nmovie_strip = sequences.new_movie(name='SourceMovie', filepath=source_path, channel=1, frame_start=0)\\n\\nsound_strip = None\\nfor strip in sequences:\\n if strip.type == 'SOUND' and strip.name.startswith('SourceMovie'):\\n sound_strip = strip\\n break\\nif not sound_strip:\\n sound_strip = sequences.new_sound(name='SourceAudio', filepath=source_path, channel=2, frame_start=0)\\n\\n# Trim to 3-second interval (75 frames at 25fps)\\ntrim_frames = 75 # 3.0s * 25fps\\nmovie_strip.frame_start = 0\\nmovie_strip.frame_final_duration = trim_frames\\nsound_strip.frame_start = 0\\nsound_strip.frame_final_duration = trim_frames\\n\\n# Apply speed effect (1.5x slowdown = 4.5s output)\\nspeed_strip = sequences.new_effect(\\n name='SpeedControl',\\n type='SPEED',\\n channel=2,\\n frame_start=0,\\n frame_end=113, # 75 frames * 1.5 = 112.5 → 113 frames\\n seq1=movie_strip,\\n seq2=None\\n)\\nspeed_strip.speed_control = 'MULTIPLY'\\nspeed_strip.speed_factor = 1/1.5\\n\\n# Set scene frame range\\nduration_frames = 113 # 4.5s * 25fps = 112.5 → 113 frames\\nscene.frame_start = 0\\nscene.frame_end = duration_frames\\n\\n# Add subtitle with background box\\ntext_strip = sequences.new_effect(\\n name='Subtitle',\\n type='TEXT',\\n channel=3,\\n frame_start=0,\\n frame_end=duration_frames,\\n seq1=None,\\n seq2=None\\n)\\ntext_strip.text = 'BIG BUNNY'\\ntext_strip.align_x = 'CENTER'\\ntext_strip.align_y = 'BOTTOM'\\ntext_strip.use_box = True\\ntext_strip.box_color = (0.0, 0.0, 0.0, 0.6)\\ntext_strip.font_size = 48\\n\\n# Render animation\\nbpy.ops.render.render(animation=True)\"}"
|
||||
},
|
||||
"usage": {
|
||||
"prompt_tokens": 821,
|
||||
"completion_tokens": 5369,
|
||||
"total_tokens": 6190
|
||||
},
|
||||
"latency_s": 111.15
|
||||
},
|
||||
{
|
||||
"purpose": "blender_script_negative-control_attempt_4",
|
||||
"provider": "ark",
|
||||
"endpoint": "https://ark.cn-beijing.volces.com/api/v3",
|
||||
"request": {
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a Blender VSE engineer. Return one JSON object only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate a complete Blender 4.3 Python script for this video edit.\n\nInput movie: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov\nOutput MP4: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4\nSource FPS: 25\nSource size: 853x480; render at 854x480 (one-pixel even-width pad required by H.264)\nTrim interval: [0.000, 3.000] seconds\nEffects: slow playback so output duration is 1.5 times the trimmed interval; add bottom-centered subtitle BIG BUNNY with a visible semi-transparent dark box.\n\nRequirements:\n- Use bpy and Blender's Video Sequence Editor, including new_movie, new_sound when available, frame_offset_start/frame_final_duration, a SPEED effect, and a TEXT effect.\n- Render exactly 854x480 at 25 fps through Blender to MPEG-4 H.264 with AAC audio.\n- Set the scene frame range to the slowed duration and call bpy.ops.render.render(animation=True).\n- Create only the requested output. Do not invoke ffmpeg, subprocesses, a shell, the network, or read credentials.\n- Use APIs available in Blender 4.3 (scene.sequence_editor_create().sequences).\n- In Blender 4.3, SpeedControlSequence has no use_audio property. Never read or assign use_audio, and do not apply a SPEED effect to the sound strip. A valid movie slow-motion pattern is speed_control='MULTIPLY', speed_factor=1/1.5, and extending the movie/render duration; the sound strip may remain normally trimmed.\n- For the subtitle background, prefer the TEXT strip's use_box=True and box_color=(0,0,0,0.6); do not assume a COLOR strip has text-layout properties.\n\nReturn one JSON object only: {\"code\":\"complete executable Python source\"}.\n\nPrior executable feedback:\nStatic safety/API validation failed: ValueError: generated script omits requested Blender API operations: ['frame_offset_start']"
|
||||
}
|
||||
],
|
||||
"temperature": 0,
|
||||
"max_tokens": 7000,
|
||||
"response_format": {
|
||||
"type": "json_object"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"id": "02178536055081715b00b15f7b15a122bee0bef9a71075821cc7c",
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"finish_reason": "stop",
|
||||
"content": "{\"code\":\"import bpy\\nimport os\\n\\n# Clear existing data\\nbpy.ops.wm.read_factory_settings(use_empty=True)\\n\\n# Get the current scene\\nscene = bpy.context.scene\\n\\n# Set render resolution (854x480 for H.264 even width)\\nscene.render.resolution_x = 854\\nscene.render.resolution_y = 480\\nscene.render.resolution_percentage = 100\\n\\n# Set frame rate (25 FPS)\\nscene.render.fps = 25\\nscene.render.fps_base = 1.0\\n\\n# Output settings\\noutput_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4'\\nscene.render.filepath = output_path\\nscene.render.image_settings.file_format = 'FFMPEG'\\nscene.render.ffmpeg.format = 'MPEG4'\\nscene.render.ffmpeg.codec = 'H.264'\\nscene.render.ffmpeg.audio_codec = 'AAC'\\nscene.render.ffmpeg.audio_mixrate = 44100\\nscene.render.ffmpeg.audio_bitrate = 192\\nscene.render.use_audio = True\\n\\n# Create sequence editor\\nscene.sequence_editor_create()\\nseq_ed = scene.sequence_editor\\n\\n# Source movie path\\nsource_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov'\\n\\n# Add video strip with trim (0.000-3.000s = 75 frames @25FPS)\\nvideo_strip = seq_ed.sequences.new_movie(\\n name='Video',\\n filepath=source_path,\\n channel=1,\\n frame_start=1\\n)\\nvideo_strip.frame_offset_start = 0 # Start at 0s of source\\nvideo_strip.frame_final_duration = 75 # Trim to 3s (75 frames)\\n\\n# Add SPEED effect for slow motion (1.5x duration)\\n speed_effect = seq_ed.sequences.new_effect(\\n name='SpeedControl',\\n type='SPEED',\\n channel=2,\\n frame_start=1,\\n seq1=video_strip\\n)\\nspeed_effect.speed_control = 'MULTIPLY'\\nspeed_effect.speed_factor = 1/1.5 # Slow playback speed\\n\\n# Extend video duration to 1.5x trimmed interval (4.5s = 112.5 frames → 113 frames)\\nvideo_strip.frame_final_duration = 113\\n\\n# Configure audio strip (trim to original 3s duration)\\nsound_strip = None\\nfor strip in seq_ed.sequences:\\n if strip.type == 'SOUND' and strip.name.startswith('Audio'):\\n sound_strip = strip\\nif sound_strip:\\n sound_strip.frame_offset_start = 0 # Start at 0s of source audio\\n sound_strip.frame_final_duration = 75 # Keep original 3s duration\\n\\n# Add subtitle text strip with background box\\ntext_strip = seq_ed.sequences.new_effect(\\n name='Subtitle',\\n type='TEXT',\\n channel=3,\\n frame_start=1,\\n frame_final_duration=113\\n)\\ntext_strip.text = 'BIG BUNNY'\\ntext_strip.align_x = 'CENTER'\\ntext_strip.align_y = 'BOTTOM'\\ntext_strip.use_box = True\\ntext_strip.box_color = (0, 0, 0, 0.6) # Semi-transparent black box\\ntext_strip.font_size = 48\\n\\n# Set scene frame range to match slowed video duration\\nscene.frame_start = 1\\nscene.frame_end = 113\\n\\n# Render the animation\\nbpy.ops.render.render(animation=True)\"}"
|
||||
},
|
||||
"usage": {
|
||||
"prompt_tokens": 643,
|
||||
"completion_tokens": 4515,
|
||||
"total_tokens": 5158
|
||||
},
|
||||
"latency_s": 97.508
|
||||
},
|
||||
{
|
||||
"purpose": "blender_script_negative-control_attempt_5",
|
||||
"provider": "ark",
|
||||
"endpoint": "https://ark.cn-beijing.volces.com/api/v3",
|
||||
"request": {
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a Blender VSE engineer. Return one JSON object only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate a complete Blender 4.3 Python script for this video edit.\n\nInput movie: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov\nOutput MP4: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4\nSource FPS: 25\nSource size: 853x480; render at 854x480 (one-pixel even-width pad required by H.264)\nTrim interval: [0.000, 3.000] seconds\nEffects: slow playback so output duration is 1.5 times the trimmed interval; add bottom-centered subtitle BIG BUNNY with a visible semi-transparent dark box.\n\nRequirements:\n- Use bpy and Blender's Video Sequence Editor, including new_movie, new_sound when available, frame_offset_start/frame_final_duration, a SPEED effect, and a TEXT effect.\n- Render exactly 854x480 at 25 fps through Blender to MPEG-4 H.264 with AAC audio.\n- Set the scene frame range to the slowed duration and call bpy.ops.render.render(animation=True).\n- Create only the requested output. Do not invoke ffmpeg, subprocesses, a shell, the network, or read credentials.\n- Use APIs available in Blender 4.3 (scene.sequence_editor_create().sequences).\n- In Blender 4.3, SpeedControlSequence has no use_audio property. Never read or assign use_audio, and do not apply a SPEED effect to the sound strip. A valid movie slow-motion pattern is speed_control='MULTIPLY', speed_factor=1/1.5, and extending the movie/render duration; the sound strip may remain normally trimmed.\n- For the subtitle background, prefer the TEXT strip's use_box=True and box_color=(0,0,0,0.6); do not assume a COLOR strip has text-layout properties.\n\nReturn one JSON object only: {\"code\":\"complete executable Python source\"}.\n\nPrior executable feedback:\nStatic safety/API validation failed: IndentationError: unexpected indent (<unknown>, line 48)"
|
||||
}
|
||||
],
|
||||
"temperature": 0,
|
||||
"max_tokens": 7000,
|
||||
"response_format": {
|
||||
"type": "json_object"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"id": "02178536064833115b00b15f7b15a122bee0bef9a710758d5fc02",
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"finish_reason": "stop",
|
||||
"content": "{\"code\":\"import bpy\\n\\n# Clear existing data\\nbpy.ops.wm.read_factory_settings(use_empty=True)\\n\\n# Get the scene\\nscene = bpy.context.scene\\n\\n# Set render resolution and FPS\\nscene.render.resolution_x = 854\\nscene.render.resolution_y = 480\\nscene.render.resolution_percentage = 100\\nscene.render.fps = 25\\nscene.render.fps_base = 1.0\\n\\n# Set output settings\\noutput_path = \\\"/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4\\\"\\nscene.render.filepath = output_path\\nscene.render.image_settings.file_format = 'FFMPEG'\\nscene.render.ffmpeg.format = 'MPEG4'\\nscene.render.ffmpeg.codec = 'H264'\\nscene.render.ffmpeg.audio_codec = 'AAC'\\nscene.render.ffmpeg.constant_rate_factor = 'MEDIUM'\\n\\n# Create sequence editor\\nseq_ed = scene.sequence_editor_create()\\n\\n# Import movie strip\\nmovie_path = \\\"/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov\\\"\\nmovie_strip = seq_ed.sequences.new_movie(\\n name=\\\"SourceMovie\\\",\\n filepath=movie_path,\\n channel=1,\\n frame_start=0\\n)\\n\\n# Trim movie to [0.000, 3.000] seconds (75 frames at 25 FPS)\\nmovie_strip.frame_offset_start = 0\\nmovie_strip.frame_final_duration = 75\\n\\n# Add speed control effect\\nspeed_strip = seq_ed.sequences.new_effect(\\n name=\\\"SpeedControl\\\",\\n type='SPEED',\\n channel=2,\\n frame_start=0,\\n frame_end=movie_strip.frame_start + movie_strip.frame_final_duration,\\n seq1=movie_strip\\n)\\nspeed_strip.speed_control = 'MULTIPLY'\\nspeed_strip.speed_factor = 1 / 1.5 # Slow down by 1.5x\\n\\n# Find sound strip and trim it\\nsound_strip = None\\nfor strip in seq_ed.sequences:\\n if strip.type == 'SOUND' and strip.frame_start == movie_strip.frame_start:\\n sound_strip = strip\\n break\\nif sound_strip:\\n sound_strip.frame_offset_start = 0\\n sound_strip.frame_final_duration = 75 # Keep sound at normal duration\\n\\n# Calculate render duration: 3s * 1.5 = 4.5s = 112.5 frames → 113 frames (0-112)\\nscene.frame_start = 0\\nscene.frame_end = 113 # 113 frames total\\n\\n# Add subtitle text strip\\ntext_strip = seq_ed.sequences.new_effect(\\n name=\\\"Subtitle\\\",\\n type='TEXT',\\n channel=3,\\n frame_start=0,\\n frame_end=scene.frame_end\\n)\\ntext_strip.text = \\\"BIG BUNNY\\\"\\ntext_strip.align_x = 'CENTER'\\ntext_strip.align_y = 'BOTTOM'\\ntext_strip.font_size = 48\\ntext_strip.color = (1, 1, 1, 1) # White text\\ntext_strip.use_box = True\\ntext_strip.box_color = (0, 0, 0, 0.6) # Dark semi-transparent box\\n\\n# Render animation\\nscene.render.engine = 'BLENDER_EEVEE'\\nbpy.ops.render.render(animation=True)\"}"
|
||||
},
|
||||
"usage": {
|
||||
"prompt_tokens": 641,
|
||||
"completion_tokens": 6960,
|
||||
"total_tokens": 7601
|
||||
},
|
||||
"latency_s": 139.053
|
||||
},
|
||||
{
|
||||
"purpose": "blender_script_negative-control_attempt_6",
|
||||
"provider": "ark",
|
||||
"endpoint": "https://ark.cn-beijing.volces.com/api/v3",
|
||||
"request": {
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a Blender VSE engineer. Return one JSON object only."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Generate a complete Blender 4.3 Python script for this video edit.\n\nInput movie: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov\nOutput MP4: /Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4\nSource FPS: 25\nSource size: 853x480; render at 854x480 (one-pixel even-width pad required by H.264)\nTrim interval: [0.000, 3.000] seconds\nEffects: slow playback so output duration is 1.5 times the trimmed interval; add bottom-centered subtitle BIG BUNNY with a visible semi-transparent dark box.\n\nRequirements:\n- Use bpy and Blender's Video Sequence Editor, including new_movie, new_sound when available, frame_offset_start/frame_final_duration, a SPEED effect, and a TEXT effect.\n- Render exactly 854x480 at 25 fps through Blender to MPEG-4 H.264 with AAC audio.\n- Set the scene frame range to the slowed duration and call bpy.ops.render.render(animation=True).\n- Create only the requested output. Do not invoke ffmpeg, subprocesses, a shell, the network, or read credentials.\n- Use APIs available in Blender 4.3 (scene.sequence_editor_create().sequences).\n- In Blender 4.3, SpeedControlSequence has no use_audio property. Never read or assign use_audio, and do not apply a SPEED effect to the sound strip. A valid movie slow-motion pattern is speed_control='MULTIPLY', speed_factor=1/1.5, and extending the movie/render duration; the sound strip may remain normally trimmed.\n- For the subtitle background, prefer the TEXT strip's use_box=True and box_color=(0,0,0,0.6); do not assume a COLOR strip has text-layout properties.\n\nReturn one JSON object only: {\"code\":\"complete executable Python source\"}.\n\nPrior executable feedback:\nBlender exit=0; output_exists=False. Tail of real Blender log:\nBlender 4.3.2 (hash 32f5fdce0a0a built 2024-12-17 02:14:25)\nTraceback (most recent call last):\n File \"/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/scripts/negative-control-attempt-5.py\", line 42, in <module>\n speed_strip = seq_ed.sequences.new_effect(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nTypeError: SequencesTopLevel.new_effect(): error with keyword argument \"frame_end\" - Function.frame_end expected an int type, not float\n\nBlender quit"
|
||||
}
|
||||
],
|
||||
"temperature": 0,
|
||||
"max_tokens": 7000,
|
||||
"response_format": {
|
||||
"type": "json_object"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"id": "02178536078809715b00b15f7b15a122bee0bef9a710758656f73",
|
||||
"model": "doubao-seed-1-6-250615",
|
||||
"finish_reason": "stop",
|
||||
"content": "{\"code\":\"import bpy\\nimport math\\n\\n# Clear existing objects\\nbpy.ops.object.select_all(action='SELECT')\\nbpy.ops.object.delete()\\n\\n# File paths\\ninput_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov'\\noutput_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4'\\n\\n# Scene setup\\nscene = bpy.context.scene\\n\\n# Render settings\\nscene.render.fps = 25\\nscene.render.fps_base = 1.0\\nscene.render.resolution_x = 854\\nscene.render.resolution_y = 480\\nscene.render.resolution_percentage = 100\\n\\n# Output format settings\\nscene.render.image_settings.file_format = 'MPEG4'\\nscene.render.ffmpeg.format = 'MPEG4'\\nscene.render.ffmpeg.codec = 'H264'\\nscene.render.ffmpeg.audio_codec = 'AAC'\\nscene.render.filepath = output_path\\n\\n# VSE setup\\nscene.sequence_editor_create()\\nseq_ed = scene.sequence_editor\\n\\n# Add video strip\\nvideo_strip = seq_ed.sequences.new_movie(\\n name='Video',\\n filepath=input_path,\\n frame_start=0,\\n channel=1\\n)\\nvideo_strip.frame_final_duration = 75 # 3s * 25fps\\n\\n# Add speed effect (1.5x slowdown)\\noriginal_duration = 75\\nnew_duration = math.ceil(original_duration * 1.5) # 113 frames (4.52s)\\nspeed_strip = seq_ed.sequences.new_effect(\\n name='SpeedControl',\\n type='SPEED',\\n channel=2,\\n frame_start=0,\\n frame_end=new_duration,\\n seq1=video_strip\\n)\\nspeed_strip.speed_control = 'MULTIPLY'\\nspeed_strip.speed_factor = 1/1.5\\n\\n# Add audio strip\\naudio_strip = seq_ed.sequences.new_sound(\\n name='Audio',\\n filepath=input_path,\\n frame_start=0,\\n channel=3\\n)\\naudio_strip.frame_final_duration = 75 # Keep original audio duration\\n\\n# Add subtitle text strip\\ntext_strip = seq_ed.sequences.new_effect(\\n name='Subtitle',\\n type='TEXT',\\n channel=4,\\n frame_start=0,\\n frame_end=new_duration\\n)\\ntext_strip.text = 'BIG BUNNY'\\ntext_strip.align_x = 'CENTER'\\ntext_strip.align_y = 'BOTTOM'\\ntext_strip.font_size = 48\\ntext_strip.use_box = True\\ntext_strip.box_color = (0, 0, 0, 0.6) # Semi-transparent black box\\n\\n# Set render frame range\\nscene.frame_start = 1\\nscene.frame_end = new_duration\\n\\n# Render animation\\nbpy.ops.render.render(animation=True)\"}"
|
||||
},
|
||||
"usage": {
|
||||
"prompt_tokens": 812,
|
||||
"completion_tokens": 6780,
|
||||
"total_tokens": 7592
|
||||
},
|
||||
"latency_s": 129.381
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import bpy
|
||||
|
||||
# Clear existing objects to start fresh
|
||||
bpy.ops.object.select_all(action='SELECT')
|
||||
bpy.ops.object.delete()
|
||||
|
||||
# Configuration paths and parameters
|
||||
INPUT_MOVIE = "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov"
|
||||
OUTPUT_MP4 = "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4"
|
||||
SOURCE_FPS = 25
|
||||
TRIM_DURATION_SECONDS = 3.0
|
||||
SLOW_FACTOR = 1.5
|
||||
RENDER_RESOLUTION = (854, 480)
|
||||
|
||||
# Calculate frame values
|
||||
trim_frames = int(TRIM_DURATION_SECONDS * SOURCE_FPS)
|
||||
slowed_frames = int(trim_frames * SLOW_FACTOR)
|
||||
scene = bpy.context.scene
|
||||
|
||||
# Create sequence editor
|
||||
seq_ed = scene.sequence_editor_create()
|
||||
|
||||
# Add movie strip with trim
|
||||
movie_strip = seq_ed.sequences.new_movie(
|
||||
name="SourceVideo",
|
||||
filepath=INPUT_MOVIE,
|
||||
channel=1,
|
||||
frame_start=1
|
||||
)
|
||||
movie_strip.frame_offset_start = 0 # Start at beginning of source
|
||||
movie_strip.frame_final_duration = trim_frames # Trim to 3 seconds
|
||||
|
||||
# Locate and trim audio strip (auto-created with movie)
|
||||
sound_strip = None
|
||||
for strip in seq_ed.sequences:
|
||||
if strip.type == 'SOUND' and strip.channel == 2 and strip.frame_start == 1:
|
||||
sound_strip = strip
|
||||
if sound_strip:
|
||||
sound_strip.frame_final_duration = trim_frames # Keep audio at original speed
|
||||
|
||||
# Add speed effect to video (slow motion)
|
||||
speed_strip = seq_ed.sequences.new_effect(
|
||||
name="SlowMotion",
|
||||
type='SPEED',
|
||||
channel=3,
|
||||
frame_start=1,
|
||||
frame_end=1 + slowed_frames - 1,
|
||||
target=movie_strip
|
||||
)
|
||||
speed_strip.speed_control = 'MULTIPLY'
|
||||
speed_strip.speed_factor = 1 / SLOW_FACTOR # 1/1.5 speed factor
|
||||
|
||||
# Add subtitle text strip with background box
|
||||
text_strip = seq_ed.sequences.new_text(
|
||||
name="Subtitle",
|
||||
text="BIG BUNNY",
|
||||
channel=4,
|
||||
frame_start=1,
|
||||
frame_end=1 + slowed_frames - 1
|
||||
)
|
||||
text_strip.align_x = 'CENTER'
|
||||
text_strip.align_y = 'BOTTOM'
|
||||
text_strip.use_box = True
|
||||
text_strip.box_color = (0.0, 0.0, 0.0, 0.6) # Black semi-transparent box
|
||||
text_strip.font_size = 48 # Visible size for 854x480 resolution
|
||||
|
||||
# Configure render settings
|
||||
scene.render.resolution_x = RENDER_RESOLUTION[0]
|
||||
scene.render.resolution_y = RENDER_RESOLUTION[1]
|
||||
scene.render.resolution_percentage = 100
|
||||
scene.render.fps = SOURCE_FPS
|
||||
scene.render.fps_base = 1.0
|
||||
scene.render.image_settings.file_format = 'FFMPEG'
|
||||
scene.render.ffmpeg.format = 'MPEG4'
|
||||
scene.render.ffmpeg.codec = 'H264'
|
||||
scene.render.ffmpeg.audio_codec = 'AAC'
|
||||
scene.render.filepath = OUTPUT_MP4
|
||||
|
||||
# Set render frame range
|
||||
scene.frame_start = 1
|
||||
scene.frame_end = 1 + slowed_frames - 1
|
||||
|
||||
# Execute render
|
||||
bpy.ops.render.render(animation=True)
|
||||
@@ -0,0 +1,79 @@
|
||||
import bpy
|
||||
|
||||
# Clear existing data
|
||||
bpy.ops.wm.read_factory_settings(use_empty=True)
|
||||
scene = bpy.context.scene
|
||||
|
||||
# Scene settings
|
||||
scene.render.resolution_x = 854
|
||||
scene.render.resolution_y = 480
|
||||
scene.render.resolution_percentage = 100
|
||||
scene.render.fps = 25
|
||||
scene.render.fps_base = 1.0
|
||||
|
||||
# Create sequence editor
|
||||
if not scene.sequence_editor:
|
||||
scene.sequence_editor_create()
|
||||
seq_ed = scene.sequence_editor
|
||||
sequences = seq_ed.sequences
|
||||
|
||||
# File paths
|
||||
input_movie = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov'
|
||||
output_mp4 = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4'
|
||||
|
||||
# Add movie strip (3 seconds = 75 frames at 25fps)
|
||||
mov_strip = sequences.new_movie(
|
||||
name='SourceMovie',
|
||||
filepath=input_movie,
|
||||
frame_start=1,
|
||||
channel=1
|
||||
)
|
||||
mov_strip.frame_offset_start = 0
|
||||
mov_strip.frame_final_duration = 75 # 3s * 25fps
|
||||
|
||||
# Locate and trim sound strip
|
||||
sound_strip = next((s for s in sequences if s.type == 'SOUND' and s.frame_start == mov_strip.frame_start), None)
|
||||
if sound_strip:
|
||||
sound_strip.frame_final_duration = 75 # Keep original audio duration
|
||||
|
||||
# Add speed effect (1.5x slowdown)
|
||||
speed_strip = sequences.new_effect(
|
||||
name='SlowMotion',
|
||||
type='SPEED',
|
||||
frame_start=1,
|
||||
channel=2,
|
||||
input_1=mov_strip
|
||||
)
|
||||
speed_strip.speed_control = 'MULTIPLY'
|
||||
speed_strip.speed_factor = 1 / 1.5
|
||||
|
||||
# Calculate slowed duration (4.5s = 112.5 frames → 113 frames)
|
||||
slowed_frames = int(4.5 * 25) + 1
|
||||
scene.frame_start = 1
|
||||
scene.frame_end = slowed_frames
|
||||
|
||||
# Add subtitle text strip
|
||||
text_strip = sequences.new_effect(
|
||||
name='Subtitle',
|
||||
type='TEXT',
|
||||
frame_start=1,
|
||||
frame_end=scene.frame_end,
|
||||
channel=3
|
||||
)
|
||||
text_strip.text = 'BIG BUNNY'
|
||||
text_strip.align_x = 'CENTER'
|
||||
text_strip.align_y = 'BOTTOM'
|
||||
text_strip.use_box = True
|
||||
text_strip.box_color = (0, 0, 0, 0.6)
|
||||
text_strip.font_size = 48
|
||||
|
||||
# Render settings
|
||||
scene.render.filepath = output_mp4
|
||||
scene.render.image_settings.file_format = 'FFMPEG'
|
||||
scene.render.ffmpeg.format = 'MPEG4'
|
||||
scene.render.ffmpeg.codec = 'H264'
|
||||
scene.render.ffmpeg.audio_codec = 'AAC'
|
||||
scene.render.ffmpeg.constant_rate_factor = 'MEDIUM'
|
||||
|
||||
# Render animation
|
||||
bpy.ops.render.render(animation=True)
|
||||
@@ -0,0 +1,84 @@
|
||||
import bpy
|
||||
import os
|
||||
|
||||
# Clear default objects
|
||||
bpy.ops.object.select_all(action='SELECT')
|
||||
bpy.ops.object.delete()
|
||||
|
||||
# Set up scene
|
||||
scene = bpy.context.scene
|
||||
scene.render.fps = 25
|
||||
scene.render.fps_base = 1.0
|
||||
scene.render.resolution_x = 854
|
||||
scene.render.resolution_y = 480
|
||||
scene.render.resolution_percentage = 100
|
||||
|
||||
# Configure output settings
|
||||
scene.render.image_settings.file_format = 'FFMPEG'
|
||||
scene.render.ffmpeg.format = 'MPEG4'
|
||||
scene.render.ffmpeg.codec = 'H264'
|
||||
scene.render.ffmpeg.audio_codec = 'AAC'
|
||||
scene.render.ffmpeg.audio_bitrate = 192
|
||||
output_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4'
|
||||
scene.render.filepath = output_path
|
||||
|
||||
# Create sequence editor
|
||||
scene.sequence_editor_create()
|
||||
sequences = scene.sequence_editor.sequences
|
||||
|
||||
# Import source movie and sound
|
||||
source_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov'
|
||||
movie_strip = sequences.new_movie(name='SourceMovie', filepath=source_path, channel=1, frame_start=0)
|
||||
|
||||
sound_strip = None
|
||||
for strip in sequences:
|
||||
if strip.type == 'SOUND' and strip.name.startswith('SourceMovie'):
|
||||
sound_strip = strip
|
||||
break
|
||||
if not sound_strip:
|
||||
sound_strip = sequences.new_sound(name='SourceAudio', filepath=source_path, channel=2, frame_start=0)
|
||||
|
||||
# Trim to 3-second interval (75 frames at 25fps)
|
||||
trim_frames = 75 # 3.0s * 25fps
|
||||
movie_strip.frame_start = 0
|
||||
movie_strip.frame_final_duration = trim_frames
|
||||
sound_strip.frame_start = 0
|
||||
sound_strip.frame_final_duration = trim_frames
|
||||
|
||||
# Apply speed effect (1.5x slowdown = 4.5s output)
|
||||
speed_strip = sequences.new_effect(
|
||||
name='SpeedControl',
|
||||
type='SPEED',
|
||||
channel=2,
|
||||
frame_start=0,
|
||||
frame_end=113, # 75 frames * 1.5 = 112.5 → 113 frames
|
||||
seq1=movie_strip,
|
||||
seq2=None
|
||||
)
|
||||
speed_strip.speed_control = 'MULTIPLY'
|
||||
speed_strip.speed_factor = 1/1.5
|
||||
|
||||
# Set scene frame range
|
||||
duration_frames = 113 # 4.5s * 25fps = 112.5 → 113 frames
|
||||
scene.frame_start = 0
|
||||
scene.frame_end = duration_frames
|
||||
|
||||
# Add subtitle with background box
|
||||
text_strip = sequences.new_effect(
|
||||
name='Subtitle',
|
||||
type='TEXT',
|
||||
channel=3,
|
||||
frame_start=0,
|
||||
frame_end=duration_frames,
|
||||
seq1=None,
|
||||
seq2=None
|
||||
)
|
||||
text_strip.text = 'BIG BUNNY'
|
||||
text_strip.align_x = 'CENTER'
|
||||
text_strip.align_y = 'BOTTOM'
|
||||
text_strip.use_box = True
|
||||
text_strip.box_color = (0.0, 0.0, 0.0, 0.6)
|
||||
text_strip.font_size = 48
|
||||
|
||||
# Render animation
|
||||
bpy.ops.render.render(animation=True)
|
||||
@@ -0,0 +1,90 @@
|
||||
import bpy
|
||||
import os
|
||||
|
||||
# Clear existing data
|
||||
bpy.ops.wm.read_factory_settings(use_empty=True)
|
||||
|
||||
# Get the current scene
|
||||
scene = bpy.context.scene
|
||||
|
||||
# Set render resolution (854x480 for H.264 even width)
|
||||
scene.render.resolution_x = 854
|
||||
scene.render.resolution_y = 480
|
||||
scene.render.resolution_percentage = 100
|
||||
|
||||
# Set frame rate (25 FPS)
|
||||
scene.render.fps = 25
|
||||
scene.render.fps_base = 1.0
|
||||
|
||||
# Output settings
|
||||
output_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4'
|
||||
scene.render.filepath = output_path
|
||||
scene.render.image_settings.file_format = 'FFMPEG'
|
||||
scene.render.ffmpeg.format = 'MPEG4'
|
||||
scene.render.ffmpeg.codec = 'H.264'
|
||||
scene.render.ffmpeg.audio_codec = 'AAC'
|
||||
scene.render.ffmpeg.audio_mixrate = 44100
|
||||
scene.render.ffmpeg.audio_bitrate = 192
|
||||
scene.render.use_audio = True
|
||||
|
||||
# Create sequence editor
|
||||
scene.sequence_editor_create()
|
||||
seq_ed = scene.sequence_editor
|
||||
|
||||
# Source movie path
|
||||
source_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov'
|
||||
|
||||
# Add video strip with trim (0.000-3.000s = 75 frames @25FPS)
|
||||
video_strip = seq_ed.sequences.new_movie(
|
||||
name='Video',
|
||||
filepath=source_path,
|
||||
channel=1,
|
||||
frame_start=1
|
||||
)
|
||||
video_strip.frame_offset_start = 0 # Start at 0s of source
|
||||
video_strip.frame_final_duration = 75 # Trim to 3s (75 frames)
|
||||
|
||||
# Add SPEED effect for slow motion (1.5x duration)
|
||||
speed_effect = seq_ed.sequences.new_effect(
|
||||
name='SpeedControl',
|
||||
type='SPEED',
|
||||
channel=2,
|
||||
frame_start=1,
|
||||
seq1=video_strip
|
||||
)
|
||||
speed_effect.speed_control = 'MULTIPLY'
|
||||
speed_effect.speed_factor = 1/1.5 # Slow playback speed
|
||||
|
||||
# Extend video duration to 1.5x trimmed interval (4.5s = 112.5 frames → 113 frames)
|
||||
video_strip.frame_final_duration = 113
|
||||
|
||||
# Configure audio strip (trim to original 3s duration)
|
||||
sound_strip = None
|
||||
for strip in seq_ed.sequences:
|
||||
if strip.type == 'SOUND' and strip.name.startswith('Audio'):
|
||||
sound_strip = strip
|
||||
if sound_strip:
|
||||
sound_strip.frame_offset_start = 0 # Start at 0s of source audio
|
||||
sound_strip.frame_final_duration = 75 # Keep original 3s duration
|
||||
|
||||
# Add subtitle text strip with background box
|
||||
text_strip = seq_ed.sequences.new_effect(
|
||||
name='Subtitle',
|
||||
type='TEXT',
|
||||
channel=3,
|
||||
frame_start=1,
|
||||
frame_final_duration=113
|
||||
)
|
||||
text_strip.text = 'BIG BUNNY'
|
||||
text_strip.align_x = 'CENTER'
|
||||
text_strip.align_y = 'BOTTOM'
|
||||
text_strip.use_box = True
|
||||
text_strip.box_color = (0, 0, 0, 0.6) # Semi-transparent black box
|
||||
text_strip.font_size = 48
|
||||
|
||||
# Set scene frame range to match slowed video duration
|
||||
scene.frame_start = 1
|
||||
scene.frame_end = 113
|
||||
|
||||
# Render the animation
|
||||
bpy.ops.render.render(animation=True)
|
||||
@@ -0,0 +1,85 @@
|
||||
import bpy
|
||||
|
||||
# Clear existing data
|
||||
bpy.ops.wm.read_factory_settings(use_empty=True)
|
||||
|
||||
# Get the scene
|
||||
scene = bpy.context.scene
|
||||
|
||||
# Set render resolution and FPS
|
||||
scene.render.resolution_x = 854
|
||||
scene.render.resolution_y = 480
|
||||
scene.render.resolution_percentage = 100
|
||||
scene.render.fps = 25
|
||||
scene.render.fps_base = 1.0
|
||||
|
||||
# Set output settings
|
||||
output_path = "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4"
|
||||
scene.render.filepath = output_path
|
||||
scene.render.image_settings.file_format = 'FFMPEG'
|
||||
scene.render.ffmpeg.format = 'MPEG4'
|
||||
scene.render.ffmpeg.codec = 'H264'
|
||||
scene.render.ffmpeg.audio_codec = 'AAC'
|
||||
scene.render.ffmpeg.constant_rate_factor = 'MEDIUM'
|
||||
|
||||
# Create sequence editor
|
||||
seq_ed = scene.sequence_editor_create()
|
||||
|
||||
# Import movie strip
|
||||
movie_path = "/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov"
|
||||
movie_strip = seq_ed.sequences.new_movie(
|
||||
name="SourceMovie",
|
||||
filepath=movie_path,
|
||||
channel=1,
|
||||
frame_start=0
|
||||
)
|
||||
|
||||
# Trim movie to [0.000, 3.000] seconds (75 frames at 25 FPS)
|
||||
movie_strip.frame_offset_start = 0
|
||||
movie_strip.frame_final_duration = 75
|
||||
|
||||
# Add speed control effect
|
||||
speed_strip = seq_ed.sequences.new_effect(
|
||||
name="SpeedControl",
|
||||
type='SPEED',
|
||||
channel=2,
|
||||
frame_start=0,
|
||||
frame_end=movie_strip.frame_start + movie_strip.frame_final_duration,
|
||||
seq1=movie_strip
|
||||
)
|
||||
speed_strip.speed_control = 'MULTIPLY'
|
||||
speed_strip.speed_factor = 1 / 1.5 # Slow down by 1.5x
|
||||
|
||||
# Find sound strip and trim it
|
||||
sound_strip = None
|
||||
for strip in seq_ed.sequences:
|
||||
if strip.type == 'SOUND' and strip.frame_start == movie_strip.frame_start:
|
||||
sound_strip = strip
|
||||
break
|
||||
if sound_strip:
|
||||
sound_strip.frame_offset_start = 0
|
||||
sound_strip.frame_final_duration = 75 # Keep sound at normal duration
|
||||
|
||||
# Calculate render duration: 3s * 1.5 = 4.5s = 112.5 frames → 113 frames (0-112)
|
||||
scene.frame_start = 0
|
||||
scene.frame_end = 113 # 113 frames total
|
||||
|
||||
# Add subtitle text strip
|
||||
text_strip = seq_ed.sequences.new_effect(
|
||||
name="Subtitle",
|
||||
type='TEXT',
|
||||
channel=3,
|
||||
frame_start=0,
|
||||
frame_end=scene.frame_end
|
||||
)
|
||||
text_strip.text = "BIG BUNNY"
|
||||
text_strip.align_x = 'CENTER'
|
||||
text_strip.align_y = 'BOTTOM'
|
||||
text_strip.font_size = 48
|
||||
text_strip.color = (1, 1, 1, 1) # White text
|
||||
text_strip.use_box = True
|
||||
text_strip.box_color = (0, 0, 0, 0.6) # Dark semi-transparent box
|
||||
|
||||
# Render animation
|
||||
scene.render.engine = 'BLENDER_EEVEE'
|
||||
bpy.ops.render.render(animation=True)
|
||||
@@ -0,0 +1,85 @@
|
||||
import bpy
|
||||
import math
|
||||
|
||||
# Clear existing objects
|
||||
bpy.ops.object.select_all(action='SELECT')
|
||||
bpy.ops.object.delete()
|
||||
|
||||
# File paths
|
||||
input_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/source.mov'
|
||||
output_path = '/Users/boj/book/ai-agent-book/chapter5/video-edit/validation/runs/exp5-6-real-blender-20260730-052206/negative_control.mp4'
|
||||
|
||||
# Scene setup
|
||||
scene = bpy.context.scene
|
||||
|
||||
# Render settings
|
||||
scene.render.fps = 25
|
||||
scene.render.fps_base = 1.0
|
||||
scene.render.resolution_x = 854
|
||||
scene.render.resolution_y = 480
|
||||
scene.render.resolution_percentage = 100
|
||||
|
||||
# Output format settings
|
||||
scene.render.image_settings.file_format = 'MPEG4'
|
||||
scene.render.ffmpeg.format = 'MPEG4'
|
||||
scene.render.ffmpeg.codec = 'H264'
|
||||
scene.render.ffmpeg.audio_codec = 'AAC'
|
||||
scene.render.filepath = output_path
|
||||
|
||||
# VSE setup
|
||||
scene.sequence_editor_create()
|
||||
seq_ed = scene.sequence_editor
|
||||
|
||||
# Add video strip
|
||||
video_strip = seq_ed.sequences.new_movie(
|
||||
name='Video',
|
||||
filepath=input_path,
|
||||
frame_start=0,
|
||||
channel=1
|
||||
)
|
||||
video_strip.frame_final_duration = 75 # 3s * 25fps
|
||||
|
||||
# Add speed effect (1.5x slowdown)
|
||||
original_duration = 75
|
||||
new_duration = math.ceil(original_duration * 1.5) # 113 frames (4.52s)
|
||||
speed_strip = seq_ed.sequences.new_effect(
|
||||
name='SpeedControl',
|
||||
type='SPEED',
|
||||
channel=2,
|
||||
frame_start=0,
|
||||
frame_end=new_duration,
|
||||
seq1=video_strip
|
||||
)
|
||||
speed_strip.speed_control = 'MULTIPLY'
|
||||
speed_strip.speed_factor = 1/1.5
|
||||
|
||||
# Add audio strip
|
||||
audio_strip = seq_ed.sequences.new_sound(
|
||||
name='Audio',
|
||||
filepath=input_path,
|
||||
frame_start=0,
|
||||
channel=3
|
||||
)
|
||||
audio_strip.frame_final_duration = 75 # Keep original audio duration
|
||||
|
||||
# Add subtitle text strip
|
||||
text_strip = seq_ed.sequences.new_effect(
|
||||
name='Subtitle',
|
||||
type='TEXT',
|
||||
channel=4,
|
||||
frame_start=0,
|
||||
frame_end=new_duration
|
||||
)
|
||||
text_strip.text = 'BIG BUNNY'
|
||||
text_strip.align_x = 'CENTER'
|
||||
text_strip.align_y = 'BOTTOM'
|
||||
text_strip.font_size = 48
|
||||
text_strip.use_box = True
|
||||
text_strip.box_color = (0, 0, 0, 0.6) # Semi-transparent black box
|
||||
|
||||
# Set render frame range
|
||||
scene.frame_start = 1
|
||||
scene.frame_end = new_duration
|
||||
|
||||
# Render animation
|
||||
bpy.ops.render.render(animation=True)
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"url": "https://download.blender.org/peach/trailer/trailer_480p.mov",
|
||||
"title": "Big Buck Bunny trailer (Blender Foundation Peach Open Movie Project)",
|
||||
"license": "Creative Commons Attribution 3.0",
|
||||
"license_url": "https://creativecommons.org/licenses/by/3.0/",
|
||||
"sha256": "36801b74638c12be9aa587e93cd18edfc9bc51a1c089ab2a19ee42beed9f497d",
|
||||
"probe": {
|
||||
"programs": [],
|
||||
"stream_groups": [],
|
||||
"streams": [
|
||||
{
|
||||
"index": 0,
|
||||
"codec_name": "h264",
|
||||
"codec_type": "video",
|
||||
"width": 853,
|
||||
"height": 480,
|
||||
"r_frame_rate": "25/1"
|
||||
},
|
||||
{
|
||||
"index": 1,
|
||||
"codec_name": "aac",
|
||||
"codec_type": "audio",
|
||||
"sample_rate": "48000",
|
||||
"channels": 6,
|
||||
"r_frame_rate": "0/0"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
|
||||
"duration": "32.995000",
|
||||
"size": "11061011"
|
||||
}
|
||||
},
|
||||
"naturally_occurring_scenes": true,
|
||||
"ground_truth": {
|
||||
"start": 9.08,
|
||||
"end": 11.2,
|
||||
"target": "the single continuous shot showing the large white rabbit walking alone in a sunny green meadow, after the ONE BIG RABBIT title and before the THREE RODENTS title",
|
||||
"method": "Human-labeled target shot bounded by ffmpeg scene-change frames; source inspection found transitions at 9.08 and 11.20 seconds.",
|
||||
"ffmpeg_scene_threshold": 0.35
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
Blender 4.3.2
|
||||
build date: 2024-12-17
|
||||
build time: 02:14:25
|
||||
build commit date: 2024-12-16
|
||||
build commit time: 21:10
|
||||
build hash: 32f5fdce0a0a
|
||||
build branch: blender-v4.3-release
|
||||
build platform: Darwin
|
||||
build type: Release
|
||||
build c flags: -Wall -Werror=implicit-function-declaration -Werror=return-type -Wno-tautological-compare -Wno-unknown-pragmas -Wno-char-subscripts -Wstrict-prototypes -Wmissing-prototypes -Wunused-parameter -Wundef -Wundef-prefix -Werror=unguarded-availability-new -mmacosx-version-min=11.2 -Xclang -fopenmp -I'/Users/blender/git/blender-v430/blender.git/lib/macos_arm64/openmp/include' -std=gnu11 -pipe -funsigned-char -fno-strict-aliasing -ffp-contract=off
|
||||
build c++ flags: -Wall -Wc++20-designator -Wno-tautological-compare -Wno-unknown-pragmas -Wno-char-subscripts -Wno-overloaded-virtual -Wno-sign-compare -Wno-invalid-offsetof -Wno-suggest-override -Wundef -Wundef-prefix -Wunused-parameter -Wmismatched-tags -Werror=unguarded-availability-new -mmacosx-version-min=11.2 -ftemplate-depth=1024 -Xclang -fopenmp -I'/Users/blender/git/blender-v430/blender.git/lib/macos_arm64/openmp/include' -pipe -funsigned-char -fno-strict-aliasing -ffp-contract=off
|
||||
build link flags: -fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Cocoa -framework Carbon -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework Metal -framework QuartzCore -framework Accelerate -liconv -Wl,-unexported_symbols_list,'/Users/blender/git/blender-v430/blender.git/source/creator/symbols_apple.map' -Xlinker -no_warn_duplicate_libraries
|
||||
build system: CMake
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 258 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 224 KiB |
|
After Width: | Height: | Size: 240 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 440 KiB |
|
After Width: | Height: | Size: 440 KiB |
|
After Width: | Height: | Size: 192 KiB |
|
After Width: | Height: | Size: 25 KiB |