canvas-recorder-lib 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BREAKING-CHANGES.md +18 -0
- package/README.md +112 -20
- package/dev/audio-builder.ts +4 -2
- package/dev/canvas-recorder.css +59 -0
- package/dev/canvas-recorder.ts +679 -51
- package/dev/delay-files.ts +1 -1
- package/dev/font-utils.ts +8 -1
- package/dev/format-editor.ts +734 -0
- package/dev/format-string.ts +110 -0
- package/dev/local-file-row.ts +107 -0
- package/dev/multi-text-dialog.ts +360 -0
- package/dev/multi-text-panel.ts +11 -0
- package/dev/player-body.ts +86 -6
- package/dev/rect-snap.ts +9 -9
- package/dev/slide-panel.ts +1 -1
- package/dev/split-dialog.ts +13 -2
- package/dev/static-image-panel.ts +35 -5
- package/dev/timeline-display.ts +50 -5
- package/dev/transcripts.ts +5 -3
- package/dev/video-clip-panel.ts +201 -15
- package/dist/dev/audio-builder.d.ts +1 -1
- package/dist/dev/audio-builder.d.ts.map +1 -1
- package/dist/dev/audio-builder.js +3 -2
- package/dist/dev/audio-builder.js.map +1 -1
- package/dist/dev/canvas-recorder.css +59 -0
- package/dist/dev/canvas-recorder.js +612 -50
- package/dist/dev/canvas-recorder.js.map +1 -1
- package/dist/dev/delay-files.js +1 -1
- package/dist/dev/delay-files.js.map +1 -1
- package/dist/dev/font-utils.d.ts.map +1 -1
- package/dist/dev/font-utils.js +9 -1
- package/dist/dev/font-utils.js.map +1 -1
- package/dist/dev/format-editor.d.ts +75 -0
- package/dist/dev/format-editor.d.ts.map +1 -0
- package/dist/dev/format-editor.js +642 -0
- package/dist/dev/format-editor.js.map +1 -0
- package/dist/dev/format-string.d.ts +62 -0
- package/dist/dev/format-string.d.ts.map +1 -0
- package/dist/dev/format-string.js +86 -0
- package/dist/dev/format-string.js.map +1 -0
- package/dist/dev/local-file-row.d.ts +22 -0
- package/dist/dev/local-file-row.d.ts.map +1 -0
- package/dist/dev/local-file-row.js +84 -0
- package/dist/dev/local-file-row.js.map +1 -0
- package/dist/dev/multi-text-dialog.d.ts +30 -0
- package/dist/dev/multi-text-dialog.d.ts.map +1 -0
- package/dist/dev/multi-text-dialog.js +297 -0
- package/dist/dev/multi-text-dialog.js.map +1 -0
- package/dist/dev/multi-text-panel.d.ts +2 -0
- package/dist/dev/multi-text-panel.d.ts.map +1 -1
- package/dist/dev/multi-text-panel.js +4 -0
- package/dist/dev/multi-text-panel.js.map +1 -1
- package/dist/dev/player-body.d.ts +1 -1
- package/dist/dev/player-body.d.ts.map +1 -1
- package/dist/dev/player-body.js +86 -6
- package/dist/dev/player-body.js.map +1 -1
- package/dist/dev/rect-snap.d.ts +1 -1
- package/dist/dev/rect-snap.js +7 -7
- package/dist/dev/rect-snap.js.map +1 -1
- package/dist/dev/slide-panel.d.ts +1 -1
- package/dist/dev/slide-panel.d.ts.map +1 -1
- package/dist/dev/slide-panel.js +1 -1
- package/dist/dev/slide-panel.js.map +1 -1
- package/dist/dev/split-dialog.d.ts.map +1 -1
- package/dist/dev/split-dialog.js +14 -2
- package/dist/dev/split-dialog.js.map +1 -1
- package/dist/dev/static-image-panel.d.ts +2 -0
- package/dist/dev/static-image-panel.d.ts.map +1 -1
- package/dist/dev/static-image-panel.js +29 -5
- package/dist/dev/static-image-panel.js.map +1 -1
- package/dist/dev/timeline-display.d.ts +23 -2
- package/dist/dev/timeline-display.d.ts.map +1 -1
- package/dist/dev/timeline-display.js +47 -5
- package/dist/dev/timeline-display.js.map +1 -1
- package/dist/dev/transcripts.d.ts.map +1 -1
- package/dist/dev/transcripts.js +5 -3
- package/dist/dev/transcripts.js.map +1 -1
- package/dist/dev/video-clip-panel.d.ts +8 -0
- package/dist/dev/video-clip-panel.d.ts.map +1 -1
- package/dist/dev/video-clip-panel.js +175 -9
- package/dist/dev/video-clip-panel.js.map +1 -1
- package/dist/lib/index.d.ts +3 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +3 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/main-control.d.ts +50 -4
- package/dist/lib/main-control.d.ts.map +1 -1
- package/dist/lib/main-control.js +94 -12
- package/dist/lib/main-control.js.map +1 -1
- package/dist/src/binary-search.js +1 -1
- package/dist/src/binary-search.js.map +1 -1
- package/dist/src/corner-rounder.d.ts +17 -0
- package/dist/src/corner-rounder.d.ts.map +1 -0
- package/dist/src/corner-rounder.js +89 -0
- package/dist/src/corner-rounder.js.map +1 -0
- package/dist/src/cross-fade.d.ts +1 -1
- package/dist/src/cross-fade.d.ts.map +1 -1
- package/dist/src/cross-fade.js +3 -3
- package/dist/src/cross-fade.js.map +1 -1
- package/dist/src/fancy-text.d.ts +116 -0
- package/dist/src/fancy-text.d.ts.map +1 -0
- package/dist/src/fancy-text.js +211 -0
- package/dist/src/fancy-text.js.map +1 -0
- package/dist/src/glib/letters-base.d.ts +1 -1
- package/dist/src/glib/letters-base.d.ts.map +1 -1
- package/dist/src/glib/letters-base.js +4 -3
- package/dist/src/glib/letters-base.js.map +1 -1
- package/dist/src/glib/line-font.d.ts +2 -2
- package/dist/src/glib/line-font.d.ts.map +1 -1
- package/dist/src/glib/line-font.js +2 -2
- package/dist/src/glib/line-font.js.map +1 -1
- package/dist/src/glib/paragraph-layout.d.ts +2 -2
- package/dist/src/glib/paragraph-layout.d.ts.map +1 -1
- package/dist/src/glib/paragraph-layout.js +1 -1
- package/dist/src/glib/paragraph-layout.js.map +1 -1
- package/dist/src/glib/path-shape-splitter.d.ts +1 -1
- package/dist/src/glib/path-shape-splitter.d.ts.map +1 -1
- package/dist/src/glib/path-shape-splitter.js +1 -1
- package/dist/src/glib/path-shape-splitter.js.map +1 -1
- package/dist/src/glib/path-shape.js +2 -2
- package/dist/src/glib/path-shape.js.map +1 -1
- package/dist/src/interpolate.d.ts +2 -2
- package/dist/src/interpolate.d.ts.map +1 -1
- package/dist/src/interpolate.js +1 -1
- package/dist/src/interpolate.js.map +1 -1
- package/dist/src/lattice.d.ts +1 -1
- package/dist/src/lattice.d.ts.map +1 -1
- package/dist/src/local-files.d.ts +129 -0
- package/dist/src/local-files.d.ts.map +1 -0
- package/dist/src/local-files.js +327 -0
- package/dist/src/local-files.js.map +1 -0
- package/dist/src/morph-animation.d.ts +1 -1
- package/dist/src/morph-animation.d.ts.map +1 -1
- package/dist/src/morph-animation.js +2 -2
- package/dist/src/morph-animation.js.map +1 -1
- package/dist/src/peano-fourier/fourier-shared.d.ts +1 -1
- package/dist/src/peano-fourier/fourier-shared.d.ts.map +1 -1
- package/dist/src/peano-fourier/fourier-shared.js +17 -4
- package/dist/src/peano-fourier/fourier-shared.js.map +1 -1
- package/dist/src/schedule-helper.d.ts +4 -4
- package/dist/src/schedule-helper.d.ts.map +1 -1
- package/dist/src/schedule-helper.js +2 -2
- package/dist/src/schedule-helper.js.map +1 -1
- package/dist/src/showable.d.ts +36 -4
- package/dist/src/showable.d.ts.map +1 -1
- package/dist/src/showable.js +37 -1
- package/dist/src/showable.js.map +1 -1
- package/dist/src/slide-components/arrow.d.ts +4 -4
- package/dist/src/slide-components/arrow.d.ts.map +1 -1
- package/dist/src/slide-components/arrow.js +2 -2
- package/dist/src/slide-components/arrow.js.map +1 -1
- package/dist/src/slide-components/cross-fade-transition.d.ts +3 -3
- package/dist/src/slide-components/cross-fade-transition.d.ts.map +1 -1
- package/dist/src/slide-components/cross-fade-transition.js +3 -3
- package/dist/src/slide-components/cross-fade-transition.js.map +1 -1
- package/dist/src/slide-components/duration-agnostic.d.ts +3 -3
- package/dist/src/slide-components/duration-agnostic.d.ts.map +1 -1
- package/dist/src/slide-components/duration-agnostic.js +1 -1
- package/dist/src/slide-components/duration-agnostic.js.map +1 -1
- package/dist/src/slide-components/fixed-duration.d.ts +1 -1
- package/dist/src/slide-components/fixed-duration.d.ts.map +1 -1
- package/dist/src/slide-components/fixed-duration.js +1 -1
- package/dist/src/slide-components/fixed-duration.js.map +1 -1
- package/dist/src/slide-components/fourier.d.ts +6 -6
- package/dist/src/slide-components/fourier.d.ts.map +1 -1
- package/dist/src/slide-components/fourier.js +6 -6
- package/dist/src/slide-components/fourier.js.map +1 -1
- package/dist/src/slide-components/frame-counter.d.ts +2 -2
- package/dist/src/slide-components/frame-counter.d.ts.map +1 -1
- package/dist/src/slide-components/frame-counter.js +1 -1
- package/dist/src/slide-components/frame-counter.js.map +1 -1
- package/dist/src/slide-components/function-graph.d.ts +2 -2
- package/dist/src/slide-components/function-graph.d.ts.map +1 -1
- package/dist/src/slide-components/function-graph.js +3 -3
- package/dist/src/slide-components/function-graph.js.map +1 -1
- package/dist/src/slide-components/halftone-shadow.d.ts +4 -4
- package/dist/src/slide-components/halftone-shadow.d.ts.map +1 -1
- package/dist/src/slide-components/halftone-shadow.js +2 -2
- package/dist/src/slide-components/halftone-shadow.js.map +1 -1
- package/dist/src/slide-components/handwriting-effect.d.ts +5 -5
- package/dist/src/slide-components/handwriting-effect.d.ts.map +1 -1
- package/dist/src/slide-components/handwriting-effect.js +5 -5
- package/dist/src/slide-components/handwriting-effect.js.map +1 -1
- package/dist/src/slide-components/hold.d.ts +3 -3
- package/dist/src/slide-components/hold.d.ts.map +1 -1
- package/dist/src/slide-components/hold.js +3 -3
- package/dist/src/slide-components/hold.js.map +1 -1
- package/dist/src/slide-components/image.d.ts +3 -3
- package/dist/src/slide-components/image.d.ts.map +1 -1
- package/dist/src/slide-components/image.js +3 -3
- package/dist/src/slide-components/image.js.map +1 -1
- package/dist/src/slide-components/in-parallel.d.ts +3 -3
- package/dist/src/slide-components/in-parallel.d.ts.map +1 -1
- package/dist/src/slide-components/in-parallel.js +2 -2
- package/dist/src/slide-components/in-parallel.js.map +1 -1
- package/dist/src/slide-components/in-series.d.ts +4 -4
- package/dist/src/slide-components/in-series.d.ts.map +1 -1
- package/dist/src/slide-components/in-series.js +5 -1
- package/dist/src/slide-components/in-series.js.map +1 -1
- package/dist/src/slide-components/live-duration.d.ts +1 -1
- package/dist/src/slide-components/live-duration.d.ts.map +1 -1
- package/dist/src/slide-components/live-duration.js +1 -1
- package/dist/src/slide-components/live-duration.js.map +1 -1
- package/dist/src/slide-components/multi-text.d.ts +76 -15
- package/dist/src/slide-components/multi-text.d.ts.map +1 -1
- package/dist/src/slide-components/multi-text.js +170 -25
- package/dist/src/slide-components/multi-text.js.map +1 -1
- package/dist/src/slide-components/rectangle.d.ts +3 -3
- package/dist/src/slide-components/rectangle.d.ts.map +1 -1
- package/dist/src/slide-components/rectangle.js +1 -1
- package/dist/src/slide-components/rectangle.js.map +1 -1
- package/dist/src/slide-components/registry.d.ts +1 -1
- package/dist/src/slide-components/registry.d.ts.map +1 -1
- package/dist/src/slide-components/registry.js +18 -18
- package/dist/src/slide-components/registry.js.map +1 -1
- package/dist/src/slide-components/serialize.d.ts +1 -1
- package/dist/src/slide-components/serialize.d.ts.map +1 -1
- package/dist/src/slide-components/serialize.js +2 -2
- package/dist/src/slide-components/serialize.js.map +1 -1
- package/dist/src/slide-components/show-error.js +2 -2
- package/dist/src/slide-components/show-error.js.map +1 -1
- package/dist/src/slide-components/simple-text.d.ts +4 -4
- package/dist/src/slide-components/simple-text.d.ts.map +1 -1
- package/dist/src/slide-components/simple-text.js +4 -4
- package/dist/src/slide-components/simple-text.js.map +1 -1
- package/dist/src/slide-components/slide-component.d.ts +5 -5
- package/dist/src/slide-components/slide-component.d.ts.map +1 -1
- package/dist/src/slide-components/slide-component.js +4 -4
- package/dist/src/slide-components/slide-component.js.map +1 -1
- package/dist/src/slide-components/slide-left.d.ts +3 -3
- package/dist/src/slide-components/slide-left.d.ts.map +1 -1
- package/dist/src/slide-components/slide-left.js +3 -3
- package/dist/src/slide-components/slide-left.js.map +1 -1
- package/dist/src/slide-components/split-video-clip.d.ts +2 -2
- package/dist/src/slide-components/split-video-clip.d.ts.map +1 -1
- package/dist/src/slide-components/split-video-clip.js +3 -3
- package/dist/src/slide-components/split-video-clip.js.map +1 -1
- package/dist/src/slide-components/text-effect.d.ts +2 -2
- package/dist/src/slide-components/text-effect.d.ts.map +1 -1
- package/dist/src/slide-components/traditional-text.d.ts +4 -4
- package/dist/src/slide-components/traditional-text.d.ts.map +1 -1
- package/dist/src/slide-components/traditional-text.js +3 -3
- package/dist/src/slide-components/traditional-text.js.map +1 -1
- package/dist/src/slide-components/video-clip.d.ts +17 -5
- package/dist/src/slide-components/video-clip.d.ts.map +1 -1
- package/dist/src/slide-components/video-clip.js +52 -11
- package/dist/src/slide-components/video-clip.js.map +1 -1
- package/dist/src/slide-components/video-info.d.ts +11 -11
- package/dist/src/slide-components/video-info.d.ts.map +1 -1
- package/dist/src/slide-components/video-info.js +32 -21
- package/dist/src/slide-components/video-info.js.map +1 -1
- package/dist/src/slow-image-sources.d.ts +7 -1
- package/dist/src/slow-image-sources.d.ts.map +1 -1
- package/dist/src/slow-image-sources.js +36 -5
- package/dist/src/slow-image-sources.js.map +1 -1
- package/dist/src/snapshot.d.ts +2 -2
- package/dist/src/snapshot.d.ts.map +1 -1
- package/dist/src/snapshot.js +4 -4
- package/dist/src/snapshot.js.map +1 -1
- package/dist/src/stroke-colors.d.ts +1 -1
- package/dist/src/stroke-colors.d.ts.map +1 -1
- package/dist/src/stroke-colors.js +4 -4
- package/dist/src/stroke-colors.js.map +1 -1
- package/dist/src/utility.d.ts +3 -4
- package/dist/src/utility.d.ts.map +1 -1
- package/dist/src/utility.js +4 -4
- package/dist/src/utility.js.map +1 -1
- package/lib/index.ts +3 -0
- package/lib/main-control.ts +119 -12
- package/package.json +7 -5
- package/src/binary-search.ts +2 -2
- package/src/corner-rounder.ts +128 -0
- package/src/cross-fade.ts +3 -3
- package/src/fancy-text.ts +255 -0
- package/src/glib/letters-base.ts +4 -3
- package/src/glib/line-font.ts +2 -2
- package/src/glib/paragraph-layout.ts +2 -2
- package/src/glib/path-shape-splitter.ts +1 -1
- package/src/glib/path-shape.ts +2 -2
- package/src/interpolate.ts +3 -3
- package/src/lattice.ts +1 -1
- package/src/local-files.ts +389 -0
- package/src/morph-animation.ts +2 -2
- package/src/peano-fourier/fourier-shared.ts +17 -4
- package/src/schedule-helper.ts +4 -4
- package/src/showable.ts +54 -4
- package/src/slide-components/arrow.ts +4 -4
- package/src/slide-components/cross-fade-transition.ts +4 -4
- package/src/slide-components/duration-agnostic.ts +3 -3
- package/src/slide-components/fixed-duration.ts +1 -1
- package/src/slide-components/fourier.ts +9 -9
- package/src/slide-components/frame-counter.ts +2 -2
- package/src/slide-components/function-graph.ts +4 -4
- package/src/slide-components/halftone-shadow.ts +4 -4
- package/src/slide-components/handwriting-effect.ts +7 -7
- package/src/slide-components/hold.ts +4 -4
- package/src/slide-components/image.ts +5 -5
- package/src/slide-components/in-parallel.ts +4 -4
- package/src/slide-components/in-series.ts +7 -4
- package/src/slide-components/live-duration.ts +1 -1
- package/src/slide-components/multi-text.ts +195 -30
- package/src/slide-components/rectangle.ts +3 -3
- package/src/slide-components/registry.ts +19 -19
- package/src/slide-components/serialize.ts +2 -2
- package/src/slide-components/show-error.ts +2 -2
- package/src/slide-components/simple-text.ts +7 -7
- package/src/slide-components/slide-component.ts +7 -7
- package/src/slide-components/slide-left.ts +4 -4
- package/src/slide-components/split-video-clip.ts +4 -4
- package/src/slide-components/text-effect.ts +2 -2
- package/src/slide-components/traditional-text.ts +5 -5
- package/src/slide-components/video-clip.ts +64 -13
- package/src/slide-components/video-info.ts +33 -21
- package/src/slow-image-sources.ts +38 -6
- package/src/snapshot.ts +4 -4
- package/src/stroke-colors.ts +4 -4
- package/src/utility.ts +5 -5
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Breaking Changes
|
|
2
|
+
|
|
3
|
+
Changes that can break a project using this library, newest first, and what to do about each.
|
|
4
|
+
This is not a full list of changes: new features and fixes aren't here.
|
|
5
|
+
|
|
6
|
+
While the version is 0.x, every breaking change comes with a new minor version (0.5 → 0.6), and nothing else does.
|
|
7
|
+
A project that depends on `"^0.5.0"` gets 0.5.x updates but never 0.6.0, so it only meets these changes when someone installs the new version on purpose.
|
|
8
|
+
|
|
9
|
+
## 0.6.0 (2026-11-05)
|
|
10
|
+
|
|
11
|
+
- **`CANVAS_WIDTH_UNITS`, `CANVAS_HEIGHT_UNITS` and `PIXELS_PER_UNIT` are gone** from `src/slide-components/video-info`.
|
|
12
|
+
The video's size can change now, from the GUI or from `canvasRecorder.size`, so a constant can't hold it.
|
|
13
|
+
Use `canvasWidthUnits()`, `canvasHeightUnits()` and `pixelsPerUnit()` instead, and call them while drawing, not when the module loads.
|
|
14
|
+
To keep the old fixed size, set it in your main program and call `canvasRecorder.lockSize()`.
|
|
15
|
+
|
|
16
|
+
## 0.5.0 (2026-10-18)
|
|
17
|
+
|
|
18
|
+
The first version on npm.
|
package/README.md
CHANGED
|
@@ -3,10 +3,20 @@
|
|
|
3
3
|
Preview, edit, annotate and record HTML canvas animations.
|
|
4
4
|
This is the tooling from [canvas-recorder](https://github.com/TradeIdeasPhilip/canvas-recorder), packaged as a library, so each video can be its own small project.
|
|
5
5
|
|
|
6
|
-
**Status:**
|
|
6
|
+
**Status:** in use for published videos.
|
|
7
|
+
It's still growing: while the version is 0.x, a change that could break your project comes with a new minor version (0.5 → 0.6), and [BREAKING-CHANGES.md](BREAKING-CHANGES.md) says what changed and how to update.
|
|
8
|
+
|
|
9
|
+
**Source:** https://github.com/TradeIdeasPhilip/canvas-recorder-lib
|
|
7
10
|
|
|
8
11
|
**API docs:** https://tradeideasphilip.github.io/canvas-recorder-lib/
|
|
9
12
|
|
|
13
|
+
**Try it:** the [Simple Video Editor](https://tradeideasphilip.github.io/canvas-recorder-lib/simple-video-editor/) is this library's player and Visual Editor with an empty project: open video clips from your computer, add text and callouts, and save an MP4.
|
|
14
|
+
Its source is in [simple-video-editor/](https://github.com/TradeIdeasPhilip/canvas-recorder-lib/tree/master/simple-video-editor).
|
|
15
|
+
|
|
16
|
+
**Showcase:** the [showcase](https://tradeideasphilip.github.io/canvas-recorder-lib/tests/showcase.html) is a series of slides that show what the library can do, one topic per slide.
|
|
17
|
+
Looking for code or ideas to copy? Start there.
|
|
18
|
+
Its source is in [test-project/src/showcase/](https://github.com/TradeIdeasPhilip/canvas-recorder-lib/tree/master/test-project/src/showcase), one file per slide.
|
|
19
|
+
|
|
10
20
|
## Use
|
|
11
21
|
|
|
12
22
|
```ts
|
|
@@ -17,9 +27,17 @@ import { myVideo } from "./my-video.ts"; // Any Showable.
|
|
|
17
27
|
// canvasRecorder.pixelWidth = 1920;
|
|
18
28
|
// canvasRecorder.pixelHeight = 1080;
|
|
19
29
|
|
|
30
|
+
// Optional. For a video drawn for one specific size.
|
|
31
|
+
// canvasRecorder.lockSize();
|
|
32
|
+
|
|
20
33
|
canvasRecorder.start(myVideo, { name: "my-video" });
|
|
21
34
|
```
|
|
22
35
|
|
|
36
|
+
The player shows the video's size (pixels and units) in four fields.
|
|
37
|
+
Unless the program calls `lockSize()`, the user can change them, and the player remembers the change for this video.
|
|
38
|
+
So read `canvasRecorder.width` and the rest while drawing, not once at startup.
|
|
39
|
+
The Save dialog can also save one file at a different size, without changing the video.
|
|
40
|
+
|
|
23
41
|
`start()` replaces the page's `<body>` with the player and its Visual Editor.
|
|
24
42
|
Leave your HTML's body empty, or put "Please wait…" in it.
|
|
25
43
|
|
|
@@ -37,15 +55,52 @@ The package includes the TypeScript source next to the compiled JavaScript, and
|
|
|
37
55
|
|
|
38
56
|
Things the first project to use this library ([riemann-surfaces-3d](https://github.com/TradeIdeasPhilip/riemann-surfaces-3d)) ran into.
|
|
39
57
|
|
|
58
|
+
### Installing
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npm install canvas-recorder-lib
|
|
62
|
+
npm install-scripts deny onnxruntime-node protobufjs
|
|
63
|
+
npm install-scripts ls # should say "No packages with unreviewed install scripts."
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- **Depend on the published version,** not `"file:../canvas-recorder-lib"`.
|
|
67
|
+
A `file:` dependency works on your machine, but GitHub's build machine has no `../canvas-recorder-lib`, so your GitHub Pages deploy fails.
|
|
68
|
+
`npm ci` doesn't notice; `tsc` stops with "Cannot find module 'canvas-recorder-lib'."
|
|
69
|
+
- **Deny those two install scripts.** npm 11 skips dependencies' install scripts until your project approves or denies them, and warns about each one.
|
|
70
|
+
Both come from `@huggingface/transformers`, which the library uses for transcription, and neither is needed in a browser.
|
|
71
|
+
`deny` records that in your `package.json`'s `allowScripts`.
|
|
72
|
+
- That field replaces any `allow-scripts` setting in your `~/.npmrc`.
|
|
73
|
+
If your `~/.npmrc` approves `fsevents` (Vite's file watcher on macOS), approve it again here: `npm install-scripts approve fsevents --no-allow-scripts-pin`.
|
|
74
|
+
In a new project that fails with `ENOMATCH`, because the first `npm install` doesn't put `fsevents` in `node_modules`.
|
|
75
|
+
Run `npm install` again (it warns that `fsevents` isn't approved), then approve it.
|
|
76
|
+
- **Expect a big `package-lock.json`.** The library's dependencies are installed in your project, including some that only Node.js uses.
|
|
77
|
+
|
|
78
|
+
### Working on the library at the same time
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm link ../canvas-recorder-lib # in your project
|
|
82
|
+
npm run watch # in canvas-recorder-lib
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
- `npm link` replaces `node_modules/canvas-recorder-lib` with a symlink to your copy, without touching `package.json` or `package-lock.json`.
|
|
86
|
+
So your deploy keeps using the published version.
|
|
87
|
+
- `npm ls canvas-recorder-lib` shows `-> ./../canvas-recorder-lib` while the link is active.
|
|
88
|
+
- Any later `npm install` or `npm ci` quietly puts the published copy back.
|
|
89
|
+
- Your project uses the library's compiled `dist/`, so keep `npm run watch` running in the library.
|
|
90
|
+
- When the library change is ready, publish a new version, then `npm install canvas-recorder-lib@<version>` in your project and commit both package files.
|
|
91
|
+
|
|
40
92
|
### Vite setup
|
|
41
93
|
|
|
42
|
-
|
|
43
|
-
Then add this to your `vite.config.js`:
|
|
94
|
+
Add this to your `vite.config.js`:
|
|
44
95
|
|
|
45
96
|
```js
|
|
46
97
|
import { defineConfig, searchForWorkspaceRoot } from "vite";
|
|
47
98
|
|
|
48
99
|
export default defineConfig({
|
|
100
|
+
base: "./",
|
|
101
|
+
resolve: {
|
|
102
|
+
dedupe: ["phil-lib"],
|
|
103
|
+
},
|
|
49
104
|
server: {
|
|
50
105
|
port: 5174, // Pick one per project, and keep it.
|
|
51
106
|
strictPort: true,
|
|
@@ -53,16 +108,28 @@ export default defineConfig({
|
|
|
53
108
|
allow: [searchForWorkspaceRoot(process.cwd()), "../canvas-recorder-lib"],
|
|
54
109
|
},
|
|
55
110
|
},
|
|
111
|
+
optimizeDeps: {
|
|
112
|
+
include: ["canvas-recorder-lib > @huggingface/transformers"],
|
|
113
|
+
},
|
|
114
|
+
build: {
|
|
115
|
+
rolldownOptions: { output: { keepNames: true } }, // Vite 8. Vite 7: rollupOptions.
|
|
116
|
+
},
|
|
56
117
|
});
|
|
57
118
|
```
|
|
58
119
|
|
|
59
|
-
- **`
|
|
120
|
+
- **`base: "./"`:** relative paths, so the build works on GitHub Pages, or in any subdirectory.
|
|
121
|
+
- **`dedupe`:** one copy of phil-lib. With the library linked, Vite would otherwise load two: yours, and the one in the library's `node_modules`.
|
|
122
|
+
- **`fs.allow`:** needed while the library is linked.
|
|
123
|
+
Without it, the server console says the transcription worker is "outside of Vite serving allow list", and transcripts fail.
|
|
60
124
|
A linked library lives outside your project. Vite serves files that are imported, but the worker is loaded by URL.
|
|
61
125
|
Setting `allow` turns off Vite's default, so your own folder has to be listed too; that's what `searchForWorkspaceRoot()` is for.
|
|
126
|
+
- **`optimizeDeps.include`:** without it, the first Import audio or transcript reloads the page, under `npm run dev` only.
|
|
127
|
+
Only the transcription worker imports that package, and Vite doesn't look inside workers when it starts, so it finds the package late and reloads to use it.
|
|
128
|
+
- **`keepNames`:** the Visual Editor writes TypeScript that names each component's class (Sync diffs, and `properties/*.txt`).
|
|
129
|
+
In a minified production build, like your GitHub Pages copy, those names come out as `hi` and `Nr` without it.
|
|
62
130
|
- **A fixed port:** the editor saves your work in the browser (IndexedDB), and the browser keeps a separate copy for each origin.
|
|
63
131
|
If another project already has the port, Vite quietly moves to the next one (5173 → 5174), and the editor seems to forget everything.
|
|
64
132
|
`strictPort` makes that an error instead.
|
|
65
|
-
- **`npm run watch`:** your project uses the library's compiled `dist/`, so keep this running in the library while you change it.
|
|
66
133
|
|
|
67
134
|
### Ports
|
|
68
135
|
|
|
@@ -75,7 +142,9 @@ For a new project, take the next number and add it here.
|
|
|
75
142
|
| 5173 | [canvas-recorder](https://github.com/TradeIdeasPhilip/canvas-recorder) (Vite's default; historical) |
|
|
76
143
|
| 5174 | [riemann-surfaces-3d](https://github.com/TradeIdeasPhilip/riemann-surfaces-3d) |
|
|
77
144
|
| 5175 | [affine-transforms](https://github.com/TradeIdeasPhilip/affine-transforms) |
|
|
78
|
-
| 5176 | `test-project/`
|
|
145
|
+
| 5176 | [`test-project/`](https://github.com/TradeIdeasPhilip/canvas-recorder-lib/tree/master/test-project) in this repo: the showcase, tests and tools |
|
|
146
|
+
| 5177 | [`simple-video-editor/`](https://github.com/TradeIdeasPhilip/canvas-recorder-lib/tree/master/simple-video-editor) in this repo |
|
|
147
|
+
| 5178 | 7-pointed-star |
|
|
79
148
|
|
|
80
149
|
### Starting the editor
|
|
81
150
|
|
|
@@ -86,12 +155,26 @@ For a new project, take the next number and add it here.
|
|
|
86
155
|
Disabling every sheet that has more than `@font-face` rules works (see `hideOurStyles()` in riemann-surfaces-3d's `src/video-editor.ts`).
|
|
87
156
|
- **Stop your own animation loop and keyboard handlers.** Otherwise typing in the Visual Editor's text boxes drives your program.
|
|
88
157
|
- **Put sound files in your `public/` folder** and refer to them as `"./name.m4a"`.
|
|
158
|
+
- **Or use files on your computer.** The Video File and Image File panels have **📂 Open file…**, which stores a URL like `local:Screen Recording.mov`.
|
|
159
|
+
The browser remembers the file, but only in this browser on this computer.
|
|
160
|
+
After a reload it may want your OK again: click **🔓 Allow local files**.
|
|
161
|
+
The Save dialog checks every local file before it starts, so a long recording can't stop halfway to ask.
|
|
162
|
+
In your own code, read media with `fetchMedia()`, which understands `local:` URLs.
|
|
89
163
|
- **Save the editor's state into your project, so it's in git.** The editor always saves inside the browser (IndexedDB), which git can't see.
|
|
90
164
|
Make a `properties/` folder, and point **💾 Save As**, the **Save defaults** checkbox, and **Save Diffs** at it.
|
|
91
165
|
The browser remembers each choice, so after the first time they keep saving there.
|
|
92
166
|
Add a `properties/README.md` explaining the three files; copy [riemann-surfaces-3d's](https://github.com/TradeIdeasPhilip/riemann-surfaces-3d/blob/master/properties/README.md).
|
|
93
167
|
- **Register your own components** with `componentRegistry.set(key, { create })`.
|
|
94
168
|
Then the Visual Editor can add, save and load them, and "TypeScript defaults" can rebuild them.
|
|
169
|
+
- **A mistake in the Visual Editor is a state, not an error.** Your components should treat it that way:
|
|
170
|
+
- Show a warning, in the editor or on the canvas. Never throw, and never a dialog box.
|
|
171
|
+
- Save it like any other state. Editing between two good states often passes through bad ones.
|
|
172
|
+
- Draw as much as still makes sense. Values in worse shape can come back from IndexedDB or a file, so fail gracefully and make them easy to fix.
|
|
173
|
+
- Throwing while saving a video is only for external failures, like an image or video that doesn't load.
|
|
174
|
+
- Assertions are still fine for the programmer's own mistakes, like a table of values checked when the program starts.
|
|
175
|
+
- **Name a replaceable child with `userEditableDescription`,** not the constructor's `description`, when your code adds one with `replaceableComponents.push()`.
|
|
176
|
+
When the editor loads saved changes, it rebuilds those children from the registry, so a `description` from your constructor comes back as the registry's default.
|
|
177
|
+
`userEditableDescription` is saved with the rest, and the diff file uses it to match each child with its TypeScript.
|
|
95
178
|
|
|
96
179
|
### Recording a program that has its own state
|
|
97
180
|
|
|
@@ -115,27 +198,36 @@ It is only downloaded if someone uses transcription.
|
|
|
115
198
|
|
|
116
199
|
## How this library is made
|
|
117
200
|
|
|
118
|
-
canvas-recorder is
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
To pick up newer code from canvas-recorder:
|
|
123
|
-
|
|
124
|
-
1. Make a branch from the previous "Verbatim import from canvas-recorder …" commit.
|
|
125
|
-
2. Run `npm run import`, and commit: "Verbatim import from canvas-recorder <hash>".
|
|
126
|
-
3. Merge that branch into master.
|
|
127
|
-
The library's hand edits stay as they are, and history only grows, so a plain `git push` works.
|
|
128
|
-
4. `npm run build`, and bump the version in package.json.
|
|
129
|
-
|
|
130
|
-
`imported-files.txt` lists what was copied, and from which commit.
|
|
201
|
+
The code came from [canvas-recorder](https://github.com/TradeIdeasPhilip/canvas-recorder), which is now historical.
|
|
202
|
+
Since 2026-10-14, this library is the master copy: new features and fixes start here.
|
|
203
|
+
`imported-files.txt` lists what was copied, and from which canvas-recorder commit.
|
|
131
204
|
|
|
132
205
|
## Build
|
|
133
206
|
|
|
134
207
|
```
|
|
135
208
|
npm install
|
|
136
209
|
npm run build # or: npm run watch
|
|
210
|
+
npm run clean # empty dist/
|
|
211
|
+
npm run docs # API docs, in docs/
|
|
137
212
|
```
|
|
138
213
|
|
|
139
214
|
Output goes to `dist/`: `.js`, `.d.ts`, source maps, plus the CSS and JSON files the JavaScript imports.
|
|
140
215
|
|
|
141
|
-
|
|
216
|
+
Every relative import names its file, like `from "./utility.ts"`, and `npm run build` stops if one doesn't.
|
|
217
|
+
tsc turns `.ts` into `.js` in `dist/`, which works everywhere; an import with no extension only works where a tool like Vite guesses it.
|
|
218
|
+
|
|
219
|
+
`build` and `watch` only add and overwrite files in `dist/`, so a project's running dev server never sees it empty.
|
|
220
|
+
A deleted or renamed source file leaves its old output behind until `npm run clean`.
|
|
221
|
+
|
|
222
|
+
A project that has linked this library (see [Working on the library at the same time](#working-on-the-library-at-the-same-time)) sees a change as soon as `npm run watch` recompiles it.
|
|
223
|
+
|
|
224
|
+
The Simple Video Editor is a separate npm project inside this repo. [simple-video-editor/README.md](simple-video-editor/README.md) says how to run it.
|
|
225
|
+
|
|
226
|
+
## Releasing
|
|
227
|
+
|
|
228
|
+
1. Bump the version. If [BREAKING-CHANGES.md](BREAKING-CHANGES.md) has an "Unreleased" section: `npm version minor --no-git-tag-version`, and replace "Unreleased" with the new version and the date.
|
|
229
|
+
Otherwise: `npm version patch --no-git-tag-version`. Commit and push.
|
|
230
|
+
2. `npm publish`. `prepublishOnly` empties and rebuilds `dist/` first, so nothing stale is published.
|
|
231
|
+
3. In each project: `npm install canvas-recorder-lib@<version>`, `npx tsc --noEmit`, and commit `package.json` and `package-lock.json`.
|
|
232
|
+
|
|
233
|
+
The API docs publish themselves on every push to master.
|
package/dev/audio-builder.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { fetchMedia } from "../src/local-files.ts";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* This creates a complete audio clip by joining multiple clips.
|
|
3
5
|
* It starts with all silence and you can add the clips wherever you need them.
|
|
@@ -45,7 +47,7 @@ export class AudioBuilder {
|
|
|
45
47
|
|
|
46
48
|
async #createNewAudioBuffer(url: string) {
|
|
47
49
|
const time1 = performance.now();
|
|
48
|
-
const response = await
|
|
50
|
+
const response = await fetchMedia(url);
|
|
49
51
|
const time2 = performance.now();
|
|
50
52
|
const encodedSource = await response.arrayBuffer();
|
|
51
53
|
const time3 = performance.now();
|
|
@@ -103,7 +105,7 @@ export class AudioBuilder {
|
|
|
103
105
|
* And the url will start with "./".
|
|
104
106
|
*
|
|
105
107
|
* CORS can be an issue depending on the server.
|
|
106
|
-
*
|
|
108
|
+
* A `local:` URL reads a file on the user's computer. See src/local-files.ts.
|
|
107
109
|
* @param startMsInDestination 0 to play the new clip at the the beginning of the video.
|
|
108
110
|
* 1000 to start this clip 1 second after the video starts.
|
|
109
111
|
*
|
package/dev/canvas-recorder.css
CHANGED
|
@@ -367,3 +367,62 @@ body {
|
|
|
367
367
|
outline: 2px solid #4a90d9;
|
|
368
368
|
outline-offset: -2px;
|
|
369
369
|
}
|
|
370
|
+
|
|
371
|
+
/* ── Multi Text editor ───────────────────────────────────────────────── */
|
|
372
|
+
|
|
373
|
+
/* The FormatEditor in dev/format-editor.ts: plain text with a menu ("chip")
|
|
374
|
+
in front of each run of text, naming its Text Format. From
|
|
375
|
+
format-editor-prototype's style.css. */
|
|
376
|
+
.format-editor {
|
|
377
|
+
min-height: 6rem;
|
|
378
|
+
padding: 0.5rem 0.75rem;
|
|
379
|
+
border: 1px solid #c7c7cc;
|
|
380
|
+
border-radius: 6px;
|
|
381
|
+
background: white;
|
|
382
|
+
/* Newlines are stored as plain "\n" characters, not <br> or <div>. */
|
|
383
|
+
white-space: pre-wrap;
|
|
384
|
+
overflow-wrap: anywhere;
|
|
385
|
+
line-height: 1.9;
|
|
386
|
+
font-size: 1.05rem;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.format-editor:focus-within {
|
|
390
|
+
outline: 2px solid #0a66d8;
|
|
391
|
+
outline-offset: 1px;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.format-chip {
|
|
395
|
+
display: inline-block;
|
|
396
|
+
margin: 0 1px;
|
|
397
|
+
vertical-align: baseline;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.format-chip select {
|
|
401
|
+
font: inherit;
|
|
402
|
+
font-size: 0.8rem;
|
|
403
|
+
line-height: 1.2;
|
|
404
|
+
padding: 0 0.15rem;
|
|
405
|
+
color: #1d1d1f;
|
|
406
|
+
background: #e3edfb;
|
|
407
|
+
border: 1px solid #9dbbe6;
|
|
408
|
+
border-radius: 4px;
|
|
409
|
+
cursor: pointer;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/* A name that isn't one of the formats this text can see. */
|
|
413
|
+
.format-chip.invalid select {
|
|
414
|
+
color: #d70015;
|
|
415
|
+
background: #fde8ea;
|
|
416
|
+
border-color: #d70015;
|
|
417
|
+
font-weight: 600;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/* In the open menu, all options except the unknown one use the normal color. */
|
|
421
|
+
.format-chip.invalid select option {
|
|
422
|
+
color: #1d1d1f;
|
|
423
|
+
font-weight: normal;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.format-chip select option.invalid {
|
|
427
|
+
color: #d70015;
|
|
428
|
+
}
|