Replay Channel helpers
These helpers let a script do with a Replay Channel what an operator does in the Replay window: mark an in and an out on the frame the channel shows, or on the frame recorded at a timecode, cue the marked stretch and play it at a chosen speed, save it as a clip in the clip bin, and list, cue, play and delete the clips there. A channel is named by its name, and a clip by its Id or by its name.
- The marks are the script's own. They are kept per channel, apart from the marks in the Replay window, and are forgotten when a project is loaded. Marking follows the Replay window's rules: an out before the in is refused, and an in after the out clears the out.
- Mark around an event by timecode.
ReplayChannelLiveTimecodegives the timecode of the newest frame recorded on the channel's angle, moved by a number of seconds, andReplayChannelLiveTimecodeFramesmoves it by a number of frames. Given a timecode,ReplayChannelMarkInandReplayChannelMarkOutmark the frame recorded there, whatever the channel shows, also while it shows no picture, as a new channel does until it is played. Only a frame already recorded can be marked, so an out after the event is marked once the recording has reached it. The newest frame recorded is a few frames behind the picture Composer is rendering, as the replay recorder takes that long to write it. - Cue, then play.
ReplayChannelCueMarksandReplayChannelCueClippause the channel on the in;ReplayChannelPlaythen plays at the speed you choose.ReplayChannelPlayClipcues and plays in one call. - At the end, the channel's At clip end setting decides. Played forward, the stretch ends on the out; played backwards, on the in. With Freeze frame, the default, the channel pauses there. With No output it shows nothing, with Return to live it goes live, and with Next clip a saved clip goes on to the next clip in the clip bin. The helpers do not change the setting.
- A clip plays from the replay recorder it was cut from, as it does in the Replay window, so cueing or playing a clip can change the angle the channel shows.
- A helper that cannot do what it is asked returns an empty string or
false, and writes the reason to the Composer log as a warning. A clip name that several clips share is refused; name the clip by its Id instead.
| Function | Returns | Description |
|---|---|---|
ReplayChannelMarkIn(channelName: string, timecode?: string) |
string |
Marks the in of a clip on the named Replay Channel, and returns its timecode (HH:MM:SS:FF), or an empty string when there is no such frame. Without a timecode it marks the frame the channel shows; with one, the frame recorded at that timecode in the newest recording of the angle the channel plays, whatever the channel shows, such as a timecode from ReplayChannelLiveTimecode. An out marked before that is earlier than the new in is cleared, as in the Replay window. The marks are the script's own, kept per channel until a project is loaded. |
ReplayChannelMarkOut(channelName: string, timecode?: string) |
string |
Marks the out of a clip on the named Replay Channel, and returns its timecode (HH:MM:SS:FF), or an empty string when there is no such frame or it is before the in; the out then stays as it was. Without a timecode it marks the frame the channel shows; with one, the frame recorded at that timecode, as ReplayChannelMarkIn does. A frame not recorded yet cannot be marked, so an out after an event is marked once it has been recorded. |
ReplayChannelLiveTimecode(channelName: string, offsetSeconds?: double) |
string |
Returns the timecode (HH:MM:SS:FF) of the newest frame recorded on the angle the named Replay Channel plays, moved by offsetSeconds: earlier when negative, later when positive, rounded to the nearest frame, whatever the channel shows. Give it to ReplayChannelMarkIn or ReplayChannelMarkOut to mark a moment before or after an event. The newest frame recorded is a few frames behind the picture being rendered, as the replay recorder takes that long to write it. Returns an empty string when the angle has no recording, or for an offset that is not a finite number or is more than 12 hours. |
ReplayChannelLiveTimecodeFrames(channelName: string, offsetFrames: double) |
string |
Returns the timecode (HH:MM:SS:FF) of the newest frame recorded on the angle the named Replay Channel plays, moved by a whole number of frames, offsetFrames, as ReplayChannelLiveTimecode moves it by seconds. Returns an empty string for a fraction of a frame, or for more frames than the recording's frame rate gives in 12 hours. |
ReplayChannelCueMarks(channelName: string) |
bool |
Cues the stretch marked on the named Replay Channel, on the angle it shows: the channel pauses on the in, and ReplayChannelPlay then plays it to its end (the out, or the in when played backwards), where the channel does what its At clip end setting says; Freeze frame, the default, pauses there. Returns false without both marks, or when the marked frames do not make a clip or are not recorded. |
ReplayChannelPlay(channelName: string, speed: double) |
bool |
Plays the named Replay Channel at a finite speed, taken to the nearest of -2, -1, -0.5, -0.25, 0, 0.25, 0.5, 1 and 2; a negative speed plays backwards and 0 pauses. A cued clip, or cued marks, play on to their end, where the channel does what its At clip end setting says. Returns false when there is no such channel, or the speed is not a finite number. |
ReplayChannelSaveClip(channelName: string, name: string, tag: string) |
string |
Saves the stretch marked on the named Replay Channel as a clip in the clip bin, as the Replay window's Save does, with the picture at the in as its thumbnail, and returns the new clip's Id. With an empty name the clip is named after its tag and in. The marks stay. Returns an empty string without both marks, or when they do not make a clip. |
ReplayChannelCueClip(channelName: string, clip: string) |
bool |
Cues a clip of the clip bin, named by its Id or its name, on the named Replay Channel: the channel pauses on the clip's in, on the angle the clip was cut from. Returns false when no clip, or more than one, has that name, or when the clip cannot be played. |
ReplayChannelPlayClip(channelName: string, clip: string, speed: double) |
bool |
Plays a clip of the clip bin, named by its Id or its name, on the named Replay Channel at once, from its in at a finite speed, or backwards from its out when the speed is negative, on the angle the clip was cut from; at its end the channel does what its At clip end setting says. Returns false when no clip, or more than one, has that name, or when the clip cannot be played. |
ReplayClipBinList(tag: string) |
string (JSON) |
Returns the clip bin as JSON, in the same shape as /api/replay/clip/list: every clip, or with a tag only the clips with that tag (an empty string for all). Parse it with JSON.parse in script. |
ReplayClipBinDelete(clip: string) |
bool |
Deletes a clip from the clip bin, named by its Id or its name, without asking. Returns false when no clip, or more than one, has that name. |
// An operator's buttons on connectors: mark, cue, then roll at half speed.
function OnConnectorMarkIn() { Project.ReplayChannelMarkIn("Replay 1"); }
function OnConnectorMarkOut() { Project.ReplayChannelMarkOut("Replay 1"); }
function OnConnectorCue() { Project.ReplayChannelCueMarks("Replay 1"); }
function OnConnectorRoll() { Project.ReplayChannelPlay("Replay 1", 0.5); }
// Save the marks as a goal, then play the first goal in the clip bin at once, at normal speed.
function OnConnectorSaveGoal() {
var id = Project.ReplayChannelSaveClip("Replay 1", "", "Goal");
if (id === "") return { result: "error", httpStatus: 409 };
var goals = JSON.parse(Project.ReplayClipBinList("Goal")).Clips;
var ok = Project.ReplayChannelPlayClip("Replay 1", goals[0].Id, 1);
return { result: ok ? "ok" : "error", httpStatus: ok ? 200 : 500 };
}
// A detector's callback: replay from two seconds before the event to one second after it, at half speed. The out is
// marked once it has been recorded, a second and a few frames later at 50 fps.
var outAt = "";
var framesToOut = 0;
function OnBallLanded(value) {
if (value !== "true") return;
Project.ReplayChannelMarkIn("Replay 1", Project.ReplayChannelLiveTimecode("Replay 1", -2));
outAt = Project.ReplayChannelLiveTimecode("Replay 1", 1);
framesToOut = 55;
}
function OnRenderFrame() {
if (outAt === "" || --framesToOut > 0) return;
if (Project.ReplayChannelMarkOut("Replay 1", outAt) === "") return; // not recorded yet: try again next frame
outAt = "";
if (Project.ReplayChannelCueMarks("Replay 1")) Project.ReplayChannelPlay("Replay 1", 0.5);
}