@animastor/player 0.1.0 → 0.1.1
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/CHANGELOG.md +23 -0
- package/README.md +4 -4
- package/package.json +4 -4
- package/src/player-routes.cjs +4 -0
- package/src/player-shared.cjs +2 -1
- package/src/scene-data.cjs +22 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1 (2026-10-17)
|
|
4
|
+
|
|
5
|
+
BOOK-RECOVER registry gate (stage 59, released via stage 61): the scene
|
|
6
|
+
storyboard read path self-healed PG for any disk book — when no PG durations
|
|
7
|
+
existed it computed them and upserted `image_units` keyed only on disk
|
|
8
|
+
presence, re-creating rows for deleted books on every client poll.
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- `GET /scene/:b/:ch/:sc/storyboard` — the `image_units` PG upsert
|
|
13
|
+
(duration self-heal) now runs only when the book is still registered
|
|
14
|
+
(owns a `books` row). Durations are still computed and returned in the
|
|
15
|
+
response; only the PG WRITE is suppressed for unregistered books.
|
|
16
|
+
|
|
17
|
+
### API
|
|
18
|
+
|
|
19
|
+
- No breaking changes. The gate rides on the existing injection seam:
|
|
20
|
+
`playerRoutes(app, redis, deps)` accepts an optional
|
|
21
|
+
`deps.isBookRegistered(bookId) → Promise<boolean>` and threads it into the
|
|
22
|
+
shared contour context (`playerShared.isBookRegistered`). When the host
|
|
23
|
+
does not inject it, behavior is identical to 0.1.0 (fail-open, legacy
|
|
24
|
+
recovery). Root exports unchanged.
|
|
25
|
+
|
|
3
26
|
## 0.1.0 — 2026-09-08
|
|
4
27
|
|
|
5
28
|
### Release preparation (npm publication)
|
package/README.md
CHANGED
|
@@ -11,9 +11,9 @@ Model and the read-side artifact-naming grammar.
|
|
|
11
11
|
**Status: EXTRACTED (0.1.0).** The playback contour physically lives in this
|
|
12
12
|
package (`src/`); the host backend consumes it only through the package
|
|
13
13
|
entrypoint. See
|
|
14
|
-
[`docs/architecture/PLAYER_ROUTE_SPLIT_CHECKLIST.md`](https://github.com/Animastor/animastor/blob/main/docs/architecture/PLAYER_ROUTE_SPLIT_CHECKLIST.md)
|
|
14
|
+
[`docs/architecture/PLAYER_ROUTE_SPLIT_CHECKLIST.md`](https://github.com/Animastor/animastor-backend/blob/main/docs/architecture/PLAYER_ROUTE_SPLIT_CHECKLIST.md)
|
|
15
15
|
(physical move COMPLETE) and
|
|
16
|
-
[`docs/architecture/PLAYER_PACKAGE_EXTRACTION_READINESS_AUDIT.md`](https://github.com/Animastor/animastor/blob/main/docs/architecture/PLAYER_PACKAGE_EXTRACTION_READINESS_AUDIT.md).
|
|
16
|
+
[`docs/architecture/PLAYER_PACKAGE_EXTRACTION_READINESS_AUDIT.md`](https://github.com/Animastor/animastor-backend/blob/main/docs/architecture/PLAYER_PACKAGE_EXTRACTION_READINESS_AUDIT.md).
|
|
17
17
|
|
|
18
18
|
## Requirements
|
|
19
19
|
|
|
@@ -87,8 +87,8 @@ GET /api/v1/preview/:b/:ch/:sc/:iuId GET /api/v1/book/:bookId/chunks
|
|
|
87
87
|
GET /api/v1/book/:bookId/assets-state
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
Guards: [`backend/tests/architecture/player-route-split.test.js`](https://github.com/Animastor/animastor/blob/main/backend/tests/architecture/player-route-split.test.js) (P1–P9) and
|
|
91
|
-
[`backend/tests/architecture/phase6-editor-player.test.js`](https://github.com/Animastor/animastor/blob/main/backend/tests/architecture/phase6-editor-player.test.js) (T1–T7).
|
|
90
|
+
Guards: [`backend/tests/architecture/player-route-split.test.js`](https://github.com/Animastor/animastor-backend/blob/main/backend/tests/architecture/player-route-split.test.js) (P1–P9) and
|
|
91
|
+
[`backend/tests/architecture/phase6-editor-player.test.js`](https://github.com/Animastor/animastor-backend/blob/main/backend/tests/architecture/phase6-editor-player.test.js) (T1–T7).
|
|
92
92
|
|
|
93
93
|
## License
|
|
94
94
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@animastor/player",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Animastor Player — playback HTTP contour: scene media serving (Range/206/ETag/If-Range), scene data (status/storyboard/timings/waveform), IU media, playback queue and assets-state. Reads book content only through the injected playerModel (VBook boundary); every host dependency arrives as an injected port — no config, no generation, no workflows, no Redis/PG/Redis internals in the package.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"animastor",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
},
|
|
32
32
|
"repository": {
|
|
33
33
|
"type": "git",
|
|
34
|
-
"url": "git+https://github.com/Animastor/animastor.git",
|
|
34
|
+
"url": "git+https://github.com/Animastor/animastor-backend.git",
|
|
35
35
|
"directory": "packages/animastor-player"
|
|
36
36
|
},
|
|
37
|
-
"homepage": "https://github.com/Animastor/animastor/tree/main/packages/animastor-player#readme",
|
|
37
|
+
"homepage": "https://github.com/Animastor/animastor-backend/tree/main/packages/animastor-player#readme",
|
|
38
38
|
"bugs": {
|
|
39
|
-
"url": "https://github.com/Animastor/animastor/issues"
|
|
39
|
+
"url": "https://github.com/Animastor/animastor-backend/issues"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@animastor/vbook-runtime": "^0.1.0"
|
package/src/player-routes.cjs
CHANGED
|
@@ -51,6 +51,9 @@ module.exports = function(app, redis, deps) {
|
|
|
51
51
|
getChunk, getAllChunks, getBookWindowStatus,
|
|
52
52
|
activeScenes, placeholderAudio, layerConfig, iuRepo,
|
|
53
53
|
sceneAssetsRepo, playerModel,
|
|
54
|
+
// Book-registry gate (read-time self-heal must not persist for a
|
|
55
|
+
// deleted/unregistered book):
|
|
56
|
+
isBookRegistered,
|
|
54
57
|
// Player-route seams (composition root provides them):
|
|
55
58
|
outputRoot, // = config.OUTPUT_DIR (injected)
|
|
56
59
|
playerPorts, // { assertBookAccess, computeVideoStartMs, computeWaveform }
|
|
@@ -73,6 +76,7 @@ module.exports = function(app, redis, deps) {
|
|
|
73
76
|
redis,
|
|
74
77
|
getChunk,
|
|
75
78
|
iuRepo,
|
|
79
|
+
isBookRegistered,
|
|
76
80
|
log,
|
|
77
81
|
});
|
|
78
82
|
|
package/src/player-shared.cjs
CHANGED
|
@@ -37,7 +37,7 @@ const naming = require('./artifact-naming.cjs');
|
|
|
37
37
|
* - playerPorts: { assertBookAccess, computeVideoStartMs, computeWaveform }
|
|
38
38
|
*/
|
|
39
39
|
function createPlayerShared(deps) {
|
|
40
|
-
const { playerModel, playerPorts, redis, getChunk, iuRepo, log } = deps;
|
|
40
|
+
const { playerModel, playerPorts, redis, getChunk, iuRepo, isBookRegistered, log } = deps;
|
|
41
41
|
const outputRoot = deps.outputRoot;
|
|
42
42
|
const ports = playerPorts || {};
|
|
43
43
|
|
|
@@ -222,6 +222,7 @@ function createPlayerShared(deps) {
|
|
|
222
222
|
get redis() { return redis; },
|
|
223
223
|
get getChunk() { return getChunk; },
|
|
224
224
|
get iuRepo() { return iuRepo; },
|
|
225
|
+
get isBookRegistered() { return isBookRegistered; },
|
|
225
226
|
get outputRoot() { return outputRoot; },
|
|
226
227
|
get log() { return log; },
|
|
227
228
|
};
|
package/src/scene-data.cjs
CHANGED
|
@@ -157,18 +157,28 @@ module.exports = function(app, ctx, deps) {
|
|
|
157
157
|
iu._end_ms = endMs;
|
|
158
158
|
cursorMs = endMs;
|
|
159
159
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
160
|
+
// Registration gate: only persist the duration self-heal for a
|
|
161
|
+
// book that is still in the registry. A deleted book whose disk
|
|
162
|
+
// book.json remains would otherwise get its image_units rows
|
|
163
|
+
// re-created here every time a client polls the scene storyboard.
|
|
164
|
+
// The in-memory durations are still computed and returned; only
|
|
165
|
+
// the PG write is suppressed.
|
|
166
|
+
const registered = typeof ctx.isBookRegistered !== 'function'
|
|
167
|
+
? true : await ctx.isBookRegistered(bookId);
|
|
168
|
+
if (registered) {
|
|
169
|
+
for (const [idx, iu] of ius.entries()) {
|
|
170
|
+
try {
|
|
171
|
+
await ctx.iuRepo.upsertImageUnit(buildId, bookId, chapterId, sceneId, iu.unit_id, {
|
|
172
|
+
scene_order: idx, text: iu.text, text_length: (iu.text || '').length,
|
|
173
|
+
text_proportion: iu.text_proportion || 0, scene_duration_sec: sceneDuration || 0,
|
|
174
|
+
estimated_duration_sec: iu.estimated_duration_sec || 0,
|
|
175
|
+
scene_audio_file: naming.sceneAudioName(bookId, chapterId, sceneId),
|
|
176
|
+
start_ms: iu._start_ms != null ? iu._start_ms : null,
|
|
177
|
+
end_ms: iu._end_ms != null ? iu._end_ms : null,
|
|
178
|
+
});
|
|
179
|
+
} catch (pgErr) {
|
|
180
|
+
console.warn('[SCENE STORYBOARD] Failed to persist IU to PG:', pgErr.message);
|
|
181
|
+
}
|
|
172
182
|
}
|
|
173
183
|
}
|
|
174
184
|
}
|