Commit Graph
3 Commits
Author SHA1 Message Date
Patryk GenschandClaude Opus 5 6feb2254b2 Index audio, dialogue tables and script→asset references
Turns the catalogue from a file listing into something you can read: a script
line like SNDQUESTION:FILENAME=KRET_E511.WAV now shows how long the recording
is, who speaks it and at which event, and plays it straight from the disc image.

Four sources feed that:

- Audio headers. RIFF/WAVE and Ogg Vorbis parsed in-process from the image
  stream, no temp files. WAV needs only the first 4 kB, so 3.3 GB of samples
  never reaches the CPU. Not routed through :core — SoundLoader wants a
  FileHandle and a live Gdx.audio, and its contribution is a standard RIFF
  header. 13 884 recordings, 20.2 h.

- wavs/wav.snd. Reksio i Kapitan Nemo packs its whole voice cast into one
  79 MB container that :core does not read, so its speech was invisible here.
  Flat length-prefixed entries holding Ogg Vorbis (oggenc.exe ships on the
  disc). The parser walks the file to its exact last byte: 3274 entries.
  Payloads stay in place — offset and length are enough to serve them, and
  seeking 82 MB into the ISO costs 45 ms.

- dialogi.dta. Pipe-separated CP1250 giving every line a speaker and the event
  that triggers it, so "what is in this file" is answerable without any speech
  recognition. Scene-definition tables share the format, so a row only counts
  as dialogue when column 0 is an identifier rather than a path. 3819 lines,
  98% resolving to real audio.

- Script references. OBJECT:FIELD=VALUE is uniform even inside CODE={...},
  which the decoder folds onto one line, so one pass catches declarations and
  names woven into behaviour code alike. 19 735 references; 97% resolve.
  Names built by concatenation (+"_DEF.DTA") are excluded, but a real leading
  underscore (_WZIECIE_JABLKA.WAV) is kept.

Languages now come from install.ini's [Language] section, with LCIDs translated
through :core's LangCodeConverter rather than a second table here — that is what
settles wavs/slo/ as Slovak. Promote copies them into edition_language, only
ever adding, so curated entries survive.

Transcription is wired to whisper.cpp but never runs on its own: a button with a
progress bar, a stop that keeps what is already computed, and a transcribe
command. Results are generated, not read off the disc, so they live in their own
table with the model and tool named, and the UI labels them as machine guesses.
The pipeline was verified with a stub binary — ffmpeg hands whisper exactly
16 kHz mono, progress and cancellation work, and per-language selection follows
wavs/<code>/. No real transcripts were stored.

Also fixes a pre-existing bug: .cols set display:grid, which beat the browser's
[hidden] rule, so the Skrypty section never actually hid.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 13:50:12 +02:00
Patryk GenschandClaude Opus 5 285b4ed316 Drop JAVA_TOOL_OPTIONS and --system from the image
JAVA_TOOL_OPTIONS made the JVM print "Picked up ..." on every invocation, and
the entrypoint already sets file.encoding through JAVA_OPTS. useradd --system
warned because the uid is above SYS_UID_MAX; the explicit uid is what matters.

Verified end to end on Docker 29.4: image builds, the full pipeline runs
inside the container against a read-only collection mount, the frontend and
MCP answer on the published port, and the database survives a restart in the
named volume. The read-only mount was confirmed to actually reject writes,
and the container runs as uid 10001, not root.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:51:39 +02:00
Patryk GenschandClaude Opus 5 02988297ec Add web frontend and Docker packaging
Frontend is a single page served from classpath resources with a JSON API
alongside it. Kept separate from the MCP tools because the consumers differ:
a model reads formatted text, a browser needs structures. Only the database
is shared.

The page has three views - catalog with edition details, copies, detected
facts with evidence and a filterable file list; script search with FTS5
snippets and a viewer; and a format breakdown. No build step, no CDN, no
dependencies; light and dark follow the system.

New `serve` command puts the frontend and MCP on one port, one process and
one database connection, which is also what the container runs. `mcp` alone
still works for a headless setup.

Docker is a two-stage build: JDK plus the Rex-EMoolator submodule to compile,
JRE for runtime. installDist rather than build, so check - and with it
verifyCoreVersion - is skipped and git is not needed in the image. The pinned
:core tag is extracted from gradle.properties at build time and passed in by
the entrypoint, otherwise copy.core_version would record "nieznana" and
derived-artifact invalidation would stop working. Properties go through
JAVA_OPTS because Gradle's launcher treats everything after the script name
as application arguments.

Compose mounts the collection read-only and keeps the database and script
cache in a named volume. The port is bound to loopback.

Not verified: the image itself does not build here, the Docker daemon is not
running on this machine. The launcher, JAVA_OPTS handling and resource
packaging were tested against the installDist output directly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:34:51 +02:00