A watch party built from a whole series or video playlist that remembers the group's progress and each member's, so someone coming back or joining late sees the items they missed and can catch up (solo, as a catch-up watch party, or by marking items watched). - StaticPartyService + StaticPartyStore: first on-disk state (JSON file under DATA_DIR, atomic debounced writes, flushed on SIGTERM) - each session is an ordinary Party linked via party.staticLink; group position is saved by the 20s sweep and resumed on the next session - PartyService.completeCurrentItem centralizes "item done" (Emby Played + static progress); new host-only "itemEnded" socket event covers the last queued item, which was never marked Played before - missed = group-completed minus watched in-app minus Emby Played - /static/:id view, create buttons on series/playlist pages, home section - Docker volume for /data, spec/static-watch-party.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
55 lines
1.9 KiB
Docker
55 lines
1.9 KiB
Docker
# Build context must be the repo root (not server/), since this also needs
|
|
# the client/ folder: docker build -f server/Dockerfile -t watchparty .
|
|
#
|
|
# Two stages: the first compiles both TypeScript projects (server/src -> JS
|
|
# via tsc, client/src -> a bundled JS+CSS via esbuild - see
|
|
# docs/architecture.md's TypeScript-migration section for why two separate
|
|
# toolchains rather than one shared build), the second is the actual
|
|
# runtime image, holding only the compiled output plus production
|
|
# dependencies - none of the TypeScript/esbuild toolchain itself ships.
|
|
|
|
FROM node:20-alpine AS build
|
|
|
|
WORKDIR /app
|
|
|
|
COPY server/package.json server/package-lock.json* ./server/
|
|
RUN cd server && npm install
|
|
COPY server/tsconfig.json ./server/
|
|
COPY server/src ./server/src
|
|
RUN cd server && npm run build
|
|
|
|
COPY client/package.json client/package-lock.json* ./client/
|
|
RUN cd client && npm install
|
|
COPY client/build.mjs ./client/
|
|
COPY client/tsconfig.json ./client/
|
|
COPY client/src ./client/src
|
|
RUN cd client && npm run build
|
|
|
|
|
|
FROM node:20-alpine
|
|
|
|
# ffmpeg - TranscodeService spawns it directly (see server/src/services/
|
|
# TranscodeService.ts) to burn PGS/image subtitles into video ourselves,
|
|
# the one gap Emby's own transcode + this app's client-side <track>
|
|
# rendering can't close between them. Unlike Emby's own text-subtitle
|
|
# burn-in, this needs no fontconfig/font packages at all - a PGS overlay
|
|
# is bitmap compositing, not text rendering.
|
|
RUN apk add --no-cache ffmpeg
|
|
|
|
WORKDIR /app
|
|
|
|
COPY server/package.json server/package-lock.json* ./server/
|
|
RUN cd server && npm install --omit=dev
|
|
|
|
COPY --from=build /app/server/dist ./server/dist
|
|
COPY --from=build /app/client/dist ./client/dist
|
|
|
|
WORKDIR /app/server
|
|
ENV PORT=3000
|
|
# Static watch parties' JSON file (StaticPartyStore) - mount a volume here
|
|
# (docker-compose.yml does), or they're lost with the container.
|
|
ENV DATA_DIR=/data
|
|
RUN mkdir -p /data
|
|
EXPOSE 3000
|
|
|
|
CMD ["node", "dist/index.js"]
|