Recording: filming the world and keeping the video
The shortest thing that works
task.spawn(function()
-- Record five seconds of what the player sees. The call waits until the
-- encoder is open, so a path back means the take is running.
local take, why = av.record("clip.mp4", { max_duration_sec = 5 })
if not take then error(why) end
-- A take is filed when it ends.
while av.is_recording() do task.wait(0.1) end
print(av.status().recordingEnd, av.status().recordingBytes)
end)
A relative name lands under /zero/runtime/recordings/. That folder lives as
long as the engine does: in the browser it is gone when the tab closes, which
is why a clip a player wants to keep has to be saved to their device.
In the browser a take under that folder is written into the page's private
storage frame by frame as it records, and stays there once it is filed: the
file reads, plays and saves like any other, and a long take holds none of
itself in the engine's memory while it records or after. A take filed
anywhere else (a world path under /zero/source/) is written into the VFS as
bytes when it ends.
Keeping a clip: av.save
-- In the handler of the button the player clicks to keep the clip:
task.spawn(function()
local ok, where, report = av.save("clip.mp4")
if not ok then print("not saved: " .. where) end
end)
The person at the screen decides where the file lands:
- In the browser, the clip downloads at once when the save rides the
player's click or key press, which is why the call belongs in a button's
click handler. A save with no such gesture behind it (a timer, the end of a
take, an agent's call) makes the page show the player an offer, which they
save with a click of their own: a browser starts a download only for a person
who just acted.
report.statereads"saved"for the first and"offered"for the second. - In a native engine, a save dialog opens in the player's downloads folder
with the clip's name filled in, and the file is written where they choose
(
report.stateis"offered"). An engine with no window refuses.
So a clip feature that downloads in one click has two controls: one that
records the take, and one, shown once the take has ended, whose click saves it.
Saving a take that is still recording is refused: it is filed when it ends.
av.save answers false and a reason for that, for a path with no file, and for
a clip too large for the browser to hold. The saved file is the take byte for
byte. userfile.save(path) saves any other file the engine holds the same way.
In the editor, a take is saved without any code: the Files panel's right-click
menu on the take (in /zero/runtime/recordings/) holds Save to this
device, and that click is the gesture the download rides.
Choosing what the take holds
max_duration_secorframesbound the take; without either it runs untilav.stop_recording().renderLayers = "all !EditorUI !debug"films the scene without the editor's chrome; add!uito leave the HUD out too (the viewport shows what the take films while it runs).cameranames the camera the take is filmed from.codecpicks the video codec fromav.status().codecs;"h264"is the one every player and site opens.cadence = "frame"films a fixed-step timeline (a cutscene) at the length it runs to however slowly the engine draws it.
man modules/av/record and man modules/av/save hold the full reference, and
av.status() reports how the last take ended and what it produced.