e4ccf5f72f5a1bbd056539ae8a05966647dae0ea
13
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e4b0419a53 |
Measure e2e 68h against what the sound is held to (#418)
The check failed in CI twice in a row (tasks 740 and 741) with the sound 61 and 52 ms ahead of the picture, against a fixed limit of 50 ms. Neither commit touched the sound timing. The limit was tighter than what the composition promises. - The sound follows the unrounded `player.time` and is started again once it lies more than `SLIP` (40 ms) off. - The check reads the picture from `videoTime`, which counts in whole frames of the cut. It can lie up to one frame (1/60 s) behind. - The first frame at 0.5 s may also come past it (0.5167 s in 740). That overshoot is now taken off. - The limit is SLIP plus one frame plus 5 ms for the audio clock moving on between the game's frame and the test's. Recomputed, the two red runs give 44.5 and 52.1 ms, under the new limit of 61.7 ms. Tests: - e2e 68 (atx): ALL PASSED, 21 checks, 68h at 16 ms. - Counter-probe: sound planned 100 ms early, 68h red at 116 ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
5b9d084dfe |
Keep a clip that starts later playing at its first frame
The e2e 68 check "a clip that starts later" was red in 3 of the last 8 suites (CI tasks 697, 703, 712). Two causes sat on top of each other. - The check measured too late. It started sampling after play(), and under CI load the clock was already at 0.05 to 0.22 s. It now starts before the click, like 68d does. - Measured early, a real bug showed: the video held for one frame at its first picture. The first picture triggers a redraw, and the game takes its first step in the same frame. readSpeed got both calls with the same frame time and divided by 1 ms. The speed came out at 16.7x, which counted as a jump, so the player paused. - readSpeed now measures a step without elapsed wall time against one frame at 60 fps. A real jump still counts as a jump. - e2e 34 "the pause holds the stream" also failed in task 712. Its cause is still open. The failure message now names the state before the pause, so the next red run shows where the samples got lost. Tests: - video-follow.test.ts 18/18, the new test is red without the fix - e2e 68 on melektaus-atx: ALL PASSED, 21 checks - Gate on melektaus-atx: CHECK EXIT 0, 314 files, 4853 tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
0701fe3856 |
Share the parts the sound devices and timelines repeated (#85)
Round 12 of the clean-up. Duplicate code had grown from 33 clones (249 lines) after round 11 to 140 clones (1263 lines), almost all of it in the panels and faces of the sound FX devices (#379 to #401). It is down to 57 clones (416 lines) now, and src is 816 lines shorter. - deviceParts.ts holds what the device panels built by hand: the head, rows of knobs, the screen style and the row layout for groups of knobs. Twelve panels use it. panel.knobs stays because the debug hooks read it. - DeviceFace is the base of the twelve faces. It finds the node and does wired, preview, commit, set, hide, reload and audition. compressorWired lives there as paramWired. - TextPool replaces ten copies of "make texts as needed, hide the rest" in the wave and video tabs, the rulers, the piano roll and the song and composition timelines. clipStrip.ts is the clip label strip the wave and video tabs share. - core/util/bytes.ts has the concat that ogg, matroska and avcColour each wrote out. - Dead code is gone: clear on the video players (never called since #402), posterFileOf and videoTimeAt (only tests called them) and easeOut (the same as glide(t, 3)). Values only used in their own file lose their export. - Comments over 125 columns are wrapped, and comments that told the history ("as before", "used to") say what is, in src and in the e2e modules. - Left alone on purpose: AnimationEditor and CompositionEditor share only the play button, and the curve panels are built differently. - Chip now places its boxes through put, which rounds. They were whole numbers already. The three row layouts are byte-identical before and after. - README lists the video and composition assets and the Videos and Compositions pages. Tests: - Gate (melektaus-atx): CHECK EXIT 0, 313 files, 4835 tests. - e2e 25, 34, 64, 65, 66, 69 (melektaus-atx): ALL PASSED, 330 checks. - TextPool without keeping its texts and framesToRoom without making room both go red. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
39c509a8e5 |
Keep a video item in a recording when the tab goes back and forth
A recording made while switching between tabs had stretches without the video item and without its sound, and in between the video stood for several frames. Two things went wrong behind another tab. - A player opened there got no first picture. It waited for requestVideoFrameCallback, which Chrome never calls behind a tab. A recording not in real time then waited 3 s per frame and took it without the video. Now the player takes its first picture as soon as it has data while the tab is hidden. - The span of a picture was learnt from steps that skipped pictures. After a time behind the tab it learnt 0.133 s instead of 1/30 s, left out seeks within that span and never corrected it. Now it learns only from steps where the time sought moved at most half a step, so no picture can lie between them. - Behind the tab a seek forgets which picture shows but keeps the span. A landing without a frame counts as the same picture only once the tab has been in front for 500 ms. Found in the user's recording 7ea9146b: 5363 frames, all 1/60 s apart, with the video missing at 10.63 s (8 frames), 43.17 s (5 frames) and 46.93 s (28 frames), and the sound gone with it. Tests: - Unit tests/viewport: 377 green, 4 new or rebuilt. With the old rule and the first picture only by requestVideoFrameCallback both new tests go red. - e2e 68 on melektaus-atx: ALL PASSED, 21 checks. New 68l: a video item that begins behind another tab has its colours exactly, and a tab switched every 350 ms gives colour changes at 0/30/60/90. - One run in five with switches had a change one frame late, so the check allows one frame either way. - Gate on melektaus-atx: green, 311 files, 4824 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
abb8fa51d8 |
Keep a recording going behind another browser tab
Chrome stops calling requestAnimationFrame for a hidden tab, and Pixi's ticker hangs on it. The run, the drawing and the recording all stood still as soon as the user switched to another tab. A plain run keeps standing still there, so a forgotten game does not play on unheard. - backgroundBeat.ts ticks the editor from a worker at the recording's fps while a recording goes and the tab is hidden, or the page has not drawn a frame of its own for 250 ms. Once the page draws again, the beat keeps out of the way. - The worker looks every 4 ms whether a tick is due. A 16 ms interval came in bursts behind a busy page, and the recording threw away the second tick of each burst. - backgroundTimers.ts and timerWorker.ts give the short waits of a recording timers in a worker. Chrome slows the page's own timers to once a second in a hidden tab. This covers the waits while saving and the wait for a video's picture after a seek. - Behind a tab Chrome does not call requestVideoFrameCallback, but the picture is there at seeked. The wait there is 10 ms instead of 150 ms while the tab is hidden. - The beat runs for Start recording, the exported game and Start recording... in the main menu. Tests: - tsc, eslint, Prettier clean - tests/viewport: 374 green, 3 new in background-beat.test.ts - e2e 68k (3 checks) on melektaus-atx with the tab really hidden: not in real time all 120 frames, colour changes every 30 frames, the blip 8 ms from green; in real time 97 of 120 frames (73 with the tab in front) - Counter-check without the beat: all three 68k checks red, 3 frames in 60 s not in real time, 7 frames in real time - Gate on melektaus-atx: green, 311 files, 4821 tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
87b2ee9402 |
Record every frame with Real time off on Start recording (#423)
At 4K and 60 fps the user's computer reaches about 39 fps in real time.
Reading each frame back from the GPU takes longer than a frame, and
neither reading back later nor the canvas route helped. With Real time
off the run moves on by one frame of the recording at a time, however
long the computer takes, so the file has every frame.
- Start recording has a new check Real time, on by default. Only the
node records so, the editor recording stays in real time.
- SteadyPace in recording.ts is the pace as a pure class. A step is
1/fps once the frame before is taken and the sound up to it is made,
otherwise 0 and the run holds. A frame's time is its number.
- The sound is made apart, as decided in the issue. AudioSwitch routes
what the run plays to the live library, or to the offline library of
a SteadySound while such a recording lasts. That library has the same
mix, buses, FX and limiter and is rendered up to each next frame.
- A driven video holds at every picture asked for, and the frame waits
for it. Its sound is decoded from the MP4 and played in step through
its bus.
- Two Chrome quirks measured and worked around. A held video hands
over the picture of a seek before seeked, so the frame callback is
asked for when the seek begins. A seek right onto where a picture
begins shows that one or the one before, so such a seek lands half a
millisecond further. Together 30 s became 10.7 s for 2 s of video.
- The notice tells how far the recording has got, and the line at the
end how long it took.
Deviations and limits:
- Input is not ignored, it still reaches the game, which runs slower.
- At most ten minutes per recording. Chrome holds the whole buffer of
the OfflineAudioContext while rendering, 230 MB for ten minutes.
- A free video plays on in real time and does not fit. A sound playing
before the start stays at the speakers.
Found along the way:
- A check in e2e 60 was red since
|
||
|
|
4d0a696327 |
Keep composition sound in step and give compositions a bus of their own
A composition's sound ran on the audio clock while its picture ran on the frames. A frame counts at most 0.1 s, so after a hitch the sound stayed ahead of the picture until the next stop. Songs in a trailer drifted off the cut. The items of a composition also had no bus of their own, and a video sprite could not pick where its sound goes. - CompositionSound.follow compares the audio clock with the picture each frame. More than 40 ms apart, it starts the sound again where the picture is. This holds in the tab and in a run. - A time scale other than 1 now restarts the sound again and again. It stays in time but comes in pieces. - The sprite of a video item shows "Driven (by composition)" as a fixed Video clock row. Video time is hidden there, because the composition sets it every frame. - Every composition has a bus in the mix and a node in the master routing. A new one goes to the master unless other compositions are linked elsewhere, apart from where the sounds go. - Audio items pick From asset, To composition, Master or a bus. New items start with To composition. Items saved before keep From asset, so music already sent through a bus does not bypass it. - Video sprites have a new row Video bus: From asset by default, the master or a bus. In a composition the default is the composition's bus, also for video sprites inside a container item. - The chosen bus is part of the key of the video player, so a sprite with another bus gets a player of its own. Found along the way: - Six tests with full lists of sprite defaults expected the old rows and now list Video bus too. Tests: - tsc, eslint, Prettier clean - Unit: 971 green in the 28 files touched - npm run check on melektaus-atx: green, 309 files, 4804 tests - e2e 68 (melektaus-atx): 13 checks green, 68i new. The sound item and the video item go into mix:cp68-cut, which goes to the master. - e2e 69 (melektaus-atx): ALL PASSED, 23 checks, 69q and 69r new. After a hitch of 500 ms the sound restarted twice and then lay 0.5 to 5 ms off the playhead. - Counter-checks in unit tests: without the comparison the hitch test fails, without the bus in the preload the run test fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
77ac9d1aaf |
Play sounds, patterns and songs on the tracks of a composition (#418)
A trailer needs its music and effects on the same timeline as its pictures. Until now a composition could only place objects, so sound had to be started by hand from a behavior and drifted against the picture. - Audio items: a sound, a clip of a sound, a pattern or a song dragged from the asset panel onto a track becomes an item as long as one pass of it. It may share a track with object and video items and overlap them. - Editing works as for other items: move, resize, trim on the left (moves the offset), fit to media, delete, copy and paste, box selection. Sounds draw their waveform, the colour tells the kind. - The inspector shows what it plays, start, length, offset, volume (-60 to +12 dB) and bus. The bus is "From asset", the master or one of the buses, as asked for in the issue. - An item longer than its material plays in rounds. Sounds and patterns start over, a song runs on in its loop. Loop marks on the item follow the same rule, a song's first mark sits at its loop end. - compositionAudio.ts turns the items into sequences, each with its own tempo. CompositionSound plays them, in the tab and in a game. - In the tab the items are heard from the playhead on, straight into the master like every tab. A scrub is silent. Playing a song or pattern in its own tab stops the composition, and the other way round. - In a game they are planned on the audio clock for the moment the composition clock reaches them, with the scheduler's LEAD made up. While the clock stands (waiting for a video, paused, placement off) they are silent and resume at the right spot. Found along the way: - The asset panel never let a song out of its list, so a song could not be dragged anywhere. Song and scene tab reject it as they reject a pattern. - The asset panel scrolled to the selected asset on every rebuild of its list, so folding a group far below the selection jumped back up. Only a new selection scrolls now. - At the end of the list, folding a group pulled every row down by the rows that went away. ScrollContainer has a new opt-in holdOffset, set only in the asset panel, that keeps the offset until the user scrolls up. Limits: a time scale other than 1 or a frame longer than 0.1 s moves the picture and not the sound. A baked song plays its notes here, not the bake. Tests: - tsc, eslint, Prettier clean. Gate on melektaus-atx green, 309 files, 4788 tests (4772 plus 16 new). - Unit: composition-audio.test.ts 13 new, scroll-container 3 new. Counter-checks: without catching up on load time or without the silence on pause the unit tests go red. - e2e 68h: the sound is planned 1.2 ms after the composition reaches 0.5 s. Without the LEAD make-up it is 54 ms late and red. - e2e 04 and 69 ALL PASSED, 86 checks. 69o-ii drags a pattern and a song onto a track, 20 frames each. - e2e 04: folding Sound at the end of the list keeps its header at y 234. With the old panel it jumps to 984 and the check is red. - Not run in a browser: the loop marks of a song item, copy and paste of audio items, the bus choice. - README and wiki count 2072 checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
65d7bf6a1f |
Silence a composition video as soon as its item ends
A video in a composition plays on a driven player that the item tells where to stand every frame. When the item ended, its object was gone and stopped asking, but the player ran on with its sound until it was let go for being unused. That took 2 to 4 seconds, and in a pause it never happened at all. The same held for the composition preview. - A driven player nobody asked for in 100 ms is now paused and muted. When its wearer comes back it carries on where it should be, as before. It is still let go after 2 to 4 seconds. - A player still without its first picture keeps playing, without sound, because it only gets that picture by playing. - Leaving the animation or composition tab now silences their video preview at once instead of after 2 to 4 seconds. - Free videos (Video clock free) keep the old behaviour. A sprite destroyed by a behavior is still heard for 2 to 4 seconds. Tests: - Unit video-library: 10 green (1 new). Without the new timer the new test is red. - e2e 68: ALL PASSED, 11 checks (68g new). An item of 0.5 s with a 2 s video plays audibly while it is there, and the player is paused and muted in every frame from about 200 ms after it ends. - Gate on melektaus-atx: green, 305 files, 4737 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
40b6290d24 |
Sample 68d's video wait from before the click on Play (#417)
CI task 669 failed in e2e 68d with no loading frame seen. The check began to sample after play(), and play() settles after the start. A video that loads quickly was ready by then, so the wait it checks had already passed. The composition itself had waited: its clock read 0 when the player was ready. - 68d starts its sampler before the click on Play and counts only frames in play mode. - The sampler stops after 20 s, not after a number of frames. Before the run the page draws far faster than 60 frames a second. Tests: - e2e 66, 67, 68 on melektaus-atx: ALL PASSED, 43 checks, 68d saw 6 loading frames at 0 and 0.32 s after Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b2b4cbad28 |
Keep a video's loading out of recordings and first frames (#417)
A Start recording right after Play composition still began with empty frames. The composition's clock waited for its video, but the recording went on and took every frame while the video loaded. A clip that starts later in the video also slipped through, because its player already had one picture while it still sought to the clip's start. - The view now counts every video sprite it leaves out as missing, not only one without any first picture. - GameRecorder takes no frame while the game view misses a video, for at most VIDEO_WAIT_MS (3 s) at a time. The recorded time stands and the sound of that time is dropped, so it stays in sync. - RecordingClock.start forgets a hold from before the first frame. Without that, the first real frames all got the time 0. - A followed player starts at 1x until the first speed reading. Before, it paused and sought every frame for about 100 ms, so the first pictures after a wait stuck and then jumped. A step faster than 4x and a time running backwards do not count as a start. - Test hooks: __gm.gameVideo(id) reads the game view's own player, TakeInfo.lastFrameAt shows when the last frame was taken. Tests: - Unit recording (clock after an early hold), video-follow (2 new, 1 adapted): 449 green in tests/core/recording, tests/viewport and tests/core/composition* - e2e 68e (a clip from 0.8 s shows that picture first and then plays), 68f (a recording that already runs takes no frame while the composition's video loads) - 68e is red without the start at 1x, 68f without the hold - README: 2038 editor checks Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
6e6b6a4d9a |
Wait for a composition's videos and copy and paste its items (#417)
A composition lost the first frames of a video item. Its clock ran while the player was still loading, in the tab and in the game. The game only waited for videos once, when it started. A composition that a behavior starts later spawned its items after that wait. - The view now records which video sprites it left out for lack of a first picture, one entry per object. - The composition tab holds its playhead while the preview misses a video, for at most VIDEO_WAIT_MS (3 s) like the game. - CompositionSystem holds a composition's clock while one of its live items misses its video. The rest of the game keeps running. - The editor play and the published game pass their view to the run as RunServices.pictures. - VIDEO_WAIT_MS moves to core/model/video.ts, because the runtime does not import from viewport/. - Videos loaded ahead for coming items do not hold the clock. Items can now be copied and pasted inside the composition tab. - Ctrl+C keeps the timing of the copied items next to the objects. - Ctrl+V pastes objects and items in one undo step. The earliest item lands at the frame under the pointer, on the track there. - Without the pointer over the tracks it lands at the playhead, on the selected track or on the top track of the selected items. - Several items keep their distances and tracks to each other. - The same copy pastes into a scene as plain objects. Objects copied from a scene do not paste into a composition, they have no timing. Tests: - Unit composition-edit, clipboard, composition-play: 3 new for pasting, 1 new for the clock waiting in the game - e2e 69i (play from the end waits for the video), 69j (paste under the pointer and at the playhead), 68d (a composition started from On start waits for its video) - each new check is red without its fix - README: 2036 editor checks Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
0334d2508d |
Place compositions in scenes and play them from behaviors (#417)
A composition can now sit in a scene like a container and play there. Its items become real objects while they run, so behaviors, colliders and events work on them as on any other object. - A composition is placeable with its own symbol, transform and render layer. The scene view shows its picture at frame 0. A click on that picture selects the placement, not a single item. - CompositionSystem spawns each item as an object under the placement when it begins, with the id <placement>~<item>. On start and the other events run. The object is destroyed when the item ends. - The top track lies in front no matter which item started first. World.arrange() orders the entity list and the scene objects. - Clips and driven videos follow the same rules as compositionAt(). Loop, restart, stop and the game pause work. - New nodes: Play composition (with restart), Stop composition and the event On composition finished. They were planned for step 4 but come now, because without autoplay nothing could play otherwise. - The editor run ignores Play composition and says so in the log. It writes into the saved project, and the items would stay behind. - contentId() moved to instance.ts. The animation system uses it for nested ids too. - Compositions get no "Sort with parent" for now. Tests: the gate passed with 301 files and 4643 tests, 18 more than step 1. 13 of them are in tests/core/composition-play.test.ts. The first gate run failed in event-order.test.ts, which counts the event nodes and now finds 19. Five counter-checks each turned exactly their test red. Two order tests stayed green without the fix at first and were rebuilt. e2e 68 is new and passed with 5 own checks. Its counter-check without arrange() failed as expected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |