Use custom elements, the JavaScript API or an iframe. All three read products or site entry manifests served over HTTP(S). Start with installation and data setup.
With a bundler, install ournotes-player@0.2.0 and import ournotes-player/element. For a plain page:
<script type="module" src="https://cdn.jsdelivr.net/npm/ournotes-player@0.2.0/dist/ournotes-player.element.min.js"></script>
<ournotes-player src="https://example.org/site/charts/100001_expert.json" controls
style="max-width: 960px"></ournotes-player>The classic script dist/ournotes-player.global.min.js also registers the element and exposes OurnotesPlayer.
The element defaults to a 16:9 aspect ratio. Changing src loads another chart; see API for attributes
and events. Story and Live2D elements use their corresponding bundles and
browser runtimes.
import { ChartPlayer } from "ournotes-player";
const player = await ChartPlayer.create(document.getElementById("stage"), {
src: "https://example.org/site/charts/100001_expert.json",
});
player.addEventListener("ended", () => console.log("done"));
document.getElementById("play").onclick = () => player.play();Provide the stage element and a play button in your page. The player fills its host with a shadow-root element.
Call player.dispose() when removing it to release its canvas, audio and other resources. ChartSession provides
playback without the wrapper's canvas management. Stories and models expose StoryPlayer and ModelPlayer.
examples/iframe.html is a chart page that accepts ?src=, with optional speed,
music=off, se=off and autoplay parameters:
<iframe src="https://example.org/player/iframe.html?src=../site/charts/100001_expert.json"
style="width: 100%; aspect-ratio: 16 / 9; border: 0" allow="autoplay; fullscreen"></iframe>Browser autoplay policy still applies. A player page hosted beside its data uses the same origin; an embedding page can then place it in an iframe from another origin.
A site generated by nnnotes 0.3.x contains:
charts.json, models.json, stories.json listings
charts/<id>.json public chart entries
models/<id>.json public model entries
stories/<id>.json public story entries
products/<sha256>.json immutable product manifests
assets/<sha256>.<ext> shared file contents
assets/<sha256>.<ext>.gz gzip storage (.br for brotli)
Regional aliases can add a region segment to entry paths. Follow the paths in the listings. Products resolve their dependencies through immutable manifests; standalone layouts also use the paths in their product references. The data format and story format describe these contracts.
| Concern | Configuration |
|---|---|
| Paths | Preserve the directory layout and resolve product files against the manifest's root. Format 2 chart/model sites use their documented site-relative paths. |
| CORS | For cross-origin playback, allow the page origin on every manifest and asset. Public static data can use Access-Control-Allow-Origin: *. |
| Immutable caching | Content-addressed assets and products/<sha256>.json can use Cache-Control: public, max-age=31536000, immutable. |
| Mutable caching | Indexes, public entry aliases and HTML pages use revalidation or a short cache lifetime. |
| Publication | Upload assets and immutable products first, then public entries/pages and indexes. Retire unused files after successful publication. |
Manifest entries record decoded sizes and, for encoded assets, stored sizes. Plain .gz files can be decoded by
the player's DecompressionStream. A server may instead send them with Content-Encoding: gzip and the logical
content type. .br files require Content-Encoding: br for Chromium playback; other browsers may also support
client-side brotli decoding. Apply one encoding layer to each stored file.
Use application/json for JSON, image/png for PNG, audio/flac for FLAC, audio/mp4 for M4A and text/plain
for GLSL. An encoded file served without Content-Encoding can use application/octet-stream or
application/gzip. Mutable JSON and HTML can use ordinary server-side compression.
ournotes-player 0.2.x reads nnnotes 0.3.x story/UI products and format 2 chart/model sites. For a manifest served
outside its normal root, use the relevant loader's base option as described in the API reference.
Run node node_modules/ournotes-player/scripts/validate-data.mjs path/to/site before serving a generated directory.
Use a browser with WebGL2, WebAudio, ES2022 modules, ResizeObserver and Custom Elements. It must support the audio and video encodings selected during export, such as AAC/FLAC audio and VP9/Opus WebM video. Audio starts from a user gesture. Load the required Cubism, MotionSync or Spine runtime before the corresponding component.
Controls support touch and adapt to narrow layouts. Live drawing follows devicePixelRatio; set pixelRatio: 1
in ChartPlayer.create to reduce the drawing buffer on a constrained device. Story quality="middle" selects
the corresponding reduced effects and resolution; see story options.
Each player owns a WebGL context, audio context and playback state. Browser context and memory limits apply; dispose players that are no longer shown. See performance for a repeatable profiling method.