← Kembali ke Lab

Godot Movie Maker dan screenshot di macOS tanpa --headless

godotapple-siliconguide

Saya ingin Godot menulis screenshot dan video pendek dari skrip di Mac saya, seperti yang dilakukannya di CI pada Linux. Godot 4.7.1 di macOS 26.5.2 tidak bisa melakukannya dalam --headless, tetapi bisa dengan renderer sungguhan dan jendela di luar layar. Satu hal belum saya pecahkan: aplikasinya tetap maju ke depan selama berjalan.

Error --headless dan empat frame dari satu run Movie Maker (frame 0, 16, 32 dan 47), ditulis dengan jendela di luar layar

Semua yang di bawah ini dijalankan pada proyek uji 640 × 360 dengan satu skrip:

extends Node2D
 
# Saves the 30th frame to the path given after "--" and quits.
var frames := 0
 
func _process(_delta: float) -> void:
	$Box.position.x = 80.0 + frames * 4.0
	frames += 1
	var args := OS.get_cmdline_user_args()
	if frames == 30 and args.size() > 0:
		await RenderingServer.frame_post_draw
		get_viewport().get_texture().get_image().save_png(args[0])
		get_tree().quit()

Apa yang dilakukan --headless saat mengambil frame

Godot.app/Contents/MacOS/Godot --headless --path . -- "$PWD/out.png"

Skrip mencapai frame 30 lalu menunggu di await RenderingServer.frame_post_draw selamanya: 15 detik kemudian prosesnya masih berjalan, dan tidak ada yang tersimpan. Membaca tekstur tanpa await langsung gagal:

ERROR: Parameter "t" is null.
   at: texture_2d_get (./servers/rendering/dummy/storage/texture_storage.h:110)

Dalam --headless Godot menjalankan renderer tiruan, jadi viewport tidak punya tekstur untuk dibaca; path di error itu adalah penyimpanan tekstur milik renderer tiruan tersebut. Di Linux, jalan pintas yang biasa adalah display X virtual di bawah renderer sungguhan. Build Godot untuk macOS menggambar lewat window server macOS dan Metal, jadi trik itu tidak bisa dipakai di Mac.

Render sungguhan, di luar layar

Biarkan renderer sungguhan, dan singkirkan jendelanya. Pengaturan jendela berlaku saat jendela dibuat, sebelum skrip apa pun berjalan, jadi selama run pengaturan itu ditaruh di override.cfg di samping project.godot:

[display]
 
window/size/no_focus=true
window/size/initial_position_type=0
window/size/initial_position=Vector2i(-6000, -6000)
window/size/always_on_top=false

Lalu jalankan aplikasinya lewat open:

open -n -W -g -j -a Godot.app --stdout run.log --stderr run.log \
  --args --path "$PWD" -- "$PWD/out.png"
rm override.cfg

-n memulai instance baru walaupun Godot sudah terbuka, -W menunggu sampai Godot keluar, -g membiarkannya di latar belakang, -j menjalankannya tersembunyi, dan --stdout serta --stderr mengembalikan output-nya ke file. Tanpa itu open membuang output, karena Godot bukan proses anak dari shell Anda. Frame kembali dalam 640 × 360 dengan warna adegan itu sendiri: rata-rata RGB 188, 117, 82, latar oranye dengan kotak biru di atasnya.

Hapus override.cfg setelah run selesai. Godot membacanya setiap kali dijalankan, jadi run yang terputus sebelum rm meninggalkan jendela yang tidak pernah mendapat fokus keyboard pada peluncuran normal berikutnya.

Movie Maker: deret PNG, lalu MP4

Movie Maker merender setiap frame pada laju tetap, jadi waktu video tidak bergantung pada seberapa cepat mesin merender:

open -n -W -g -j -a Godot.app --stdout run.log --stderr run.log \
  --args --path "$PWD" --write-movie "$PWD/movie/f.png" --fixed-fps 24 --quit-after 48
48 frames at 24 FPS (movie length: 00:00:02:00), recorded in 00:00:01 (200% of real-time speed).

Movie Maker menulis f00000000.png sampai f00000047.png, dengan audio di sampingnya sebagai f.wav. ffmpeg mengubah frame-frame itu menjadi video:

ffmpeg -framerate 24 -i movie/f%08d.png -c:v libx264 -pix_fmt yuv420p -crf 18 film.mp4

Hasilnya 48 frame pada 24 fps, sepanjang 2,0 detik.

Belum terpecahkan: fokus

no_focus mencegah jendela mengambil fokus keyboard, tetapi Godot tetap menjadikan dirinya aplikasi aktif saat membuka jendelanya. Saya memeriksa aplikasi paling depan berulang kali selama dua run. Godot ada di depan dalam 1 dari 21 sampel pada run satu frame dan dalam 4 sampel berturut-turut pada run Movie Maker, yang memakan waktu sekitar satu detik, dan aplikasi yang sedang saya pakai kembali ke depan setiap kali Godot keluar. Pada September, salinan bundle aplikasi dengan LSUIElement bernilai true juga tidak membantu. Berapa lama Godot bertahan di depan selama perekaman yang lebih panjang, belum saya ukur.

Batasan