define_recordtarget(3)

πŸ“¦
version 0.7.1 Β· 2 versions
, in nixos 26.05

πŸ’– NAME πŸ’–

okay so this is define_recordtarget(3) from the Arcan Lua API, and it is literally here to create a rendertarget with a periodic readback. bestie, it’s giving β€œscreen recorder but make it Unix” πŸ’…βœ¨


🌸 SYNOPSIS 🌸

the synopsis is overload city, and the return vibe is nil:

nil
define_recordtarget( vid:buffer, string:resource, string:arguments,
vidtbl:vids )
define_recordtarget( aidtbl:aids, int:detach, int:scale, int:samplerate,
function:callback )
define_recordtarget( vid:buffer, vid:resource, string:arguments,
vidtbl:vids )
define_recordtarget( aidtbl:aids, int:detach, int:scale, int:samplerate,
function:callback )

πŸ¦‹ DESCRIPTION πŸ¦‹

so this function inherits from define_rendertarget. please refer to the description of that function for assistance with the detach, scale and samplerate arguments. yes, go read the parent function too, it’s giving family lore 🫢

there are two distinct cases for using recordtargets. one is to create a new frameserver (afsrv_encode process) session used for features such as streaming and remote displays i.e. lossy output. lossy output, iconic behavior, no notes 😌

in this case, resource will be used as the output resource path which will either be mapped to a NULL file (in the case of container=stream in arguments or "") or created in the APPL_TEMP namespace, and passed as a file descriptor into the process on creation. arguments will be forwarded using the ARCAN_ARG environment variable. ARCAN_ARG =help afsrv_encode from a command-line can be used to see the possible values for arguments. slay, the environment variable is doing its little job 🌈

the second usecase is creating an output segment in an existing client. here, arguments will be ignored and resource is expected to refer to a valid (valid_vid) frameserver segment. trying to push a subsegment to a VID that is not a connected frameserver is a terminal state transition. like, do not do that, bestie πŸ’€

the callback argument should point to a Lua defined function that accepts a source_id (will match dest_buffer) and a table with members that describe events that are performed on the underlying segment. very β€œtell me what happened on the inside” energy πŸ”₯

aids should either be a table of valid AIDs that should be mixed and forwarded, or to WORLDID as a means of hooking all arcan managed audio input. by default, they are mixed and clipped equally. this can be changed using recordtarget_gain. audio girlies, this one’s for you πŸŽ€


🎬 EXAMPLE 🎬

this first example is the full little art-project moment, obsessed:

function define_recordtarget0()
      a = fill_surface(64, 64, 128, 0, 0);
      b = fill_surface(32, 32, 0, 128, 0);
      c = fill_surface(16, 16, 0, 0, 128);
      move_image(b, VRESW - 32, 0);
      move_image(c, VRESW - 16, VRESH - 16);
      show_image({a,b,c});
      move_image(a, VRESW - 64, 0, 100);
      move_image(b, VRESW - 32, VRESH - 32, 100);
      move_image(c, 0, VRESH - 16, 100);
      move_image(a, VRESW - 64, VRESH - 64, 100);
      move_image(b, 0, VRESH - 32, 100);
      move_image(c, 0, 0, 100);
      image_transform_cycle(a, 1);
      image_transform_cycle(b, 1);
      image_transform_cycle(c, 1);
      dst = alloc_surface(VRESW * 0.5, VRESH * 0.5);
      define_recordtarget(dst, "output.mkv", "vpreset=8:noaudio:fps=25", {a,c}, {},
            RENDERTARGET_NODETACH, RENDERTARGET_SCALE, -4);
end

🎬 EXAMPLE 🎬

and here’s the second one, with the VNC vibe and a callback that literally prints the status table 🫢

function define_recordtarget1()
      a = fill_surface(64, 64, 128, 0, 0);
      move_image(a, VRESW - 64, 0, 100);
      move_image(a, VRESW - 64, VRESH - 64 ,100);
      cycle_image_transform(a);
      dst = alloc_surface(VRESW * 0.5, VRESH * 0.5);
      define_recordtarget(dst, "", "protocol=vnc:port=6200:fps=10", {a}, {},
            RENDERTARGET_NODETACH, RENDERTARGET_SCALE, -4, function(source, status)
            for k,v in pairs(status) do
                  print("key:", k, "value:", v);
            end
      end);
end

🚨 MISUSE 🚨

do not do this, bestie. this is the cautionary tale section 😭

function define_recordtarget0()
      define_recordtarget(nil, "output.mkv", "vpreset=8:noaudio:fps=25", {}, {},
            RENDERTARGET_NODETACH, RENDERTARGET_SCALE, -4);
end

🚨 MISUSE 🚨

and here’s another one for the group chat receipts πŸ™ˆ

function define_recordtarget1()
      dst = fill_surface(VRESW, VRESH, 0, 0, 0);
      define_recordtarget(dst, "output.mkv", "vpreset=11:noaudio:fps120", "", "",
            RENDERTARGET_NODETACH, RENDERTARGET_SCALE, -4);
end

πŸ‘€ SEE ALSO πŸ‘€


mwah, catch you in the source β€” this iconic page is from targetcontrol, dated October 2026, and it ate πŸ’…βœ¨πŸ‘‘

πŸ“¦ where this page comes from