Repository navigation
Full Changelog: v1.2.2...v1.3.0
Features
- Completed plays in admin analytics —
AdminAnalyticsSchema(GET /admin/analytics) carriescompletedPlaysCount, the plays intotalPlaysCountthat finished their title.totalPlaysCountnow also counts interrupted playback sessions that reached the minimum play time (server settingsystem.analytics.minPlaySeconds). - Trickplay regeneration for several titles —
admin.regenerateTrickplay({ scope: "titles", ids, force })queues the previews of up to 50 titles as one operation.TrickplayRegenerateRequestSchemaaccepts that shape next to the single library, title and season scopes. - Live session log link —
admin.getLiveSessionLogUrl(sessionId)returns the URL of a playback session's log archive (ZIP), served byGET /admin/live-activity/:sessionId/log. - Library scan progress —
libraries.getScanProgress()forGET /libraries/scan-progresslists the queued and running library scans withprogressPercent, which is null while a scan discovers files.LibraryScanProgressResponseSchema/LibraryScanProgressResponsedescribe the reply. - Scan findings can be ignored —
libraries.getScanFindings(libraryId, status)lists theactiveorignoredfindings and returnscountsfor both.libraries.setScanFindingIgnored(libraryId, { filePath, ignored })ignores a finding until it is restored, and a rescan keeps it ignored.libraries.getScanFindingCandidates(libraryId, filePath)searches the providers for the title parsed from the file name; a scan never runs that search. TheScanFinding*schemas and types describe the replies. - Playback view limits —
PlaybackViewResponse.effectivePreferencesreports the bitrate cap that applies to the profile's streams (the lower of the profile and server caps,nullwhen neither is set) and the HDR mode. - Overwrite locked fields on rematch — the rematch body accepts
overwriteLocked(defaultfalse). Locked fields keep their values unless it istrue. - Notify every administrator —
host.notifications.createForAdmins({ type, title, message?, data?, link? })sends one notification to each administrator. Each recipient counts against the plugin's daily notification limit. - Code block for plugin UI — a
codeschema node shows read-only, preformatted text that keeps its line breaks and scrolls. Plugin authors get thecode()helper from@reelvault/sdk/ui/schema. - Profile bitrate cap —
ProfilePreferences,UpdateProfilePreferencesandProfilePreferenceDefaultscarrymaxStreamingBitrateKbps(0 = no limit, up to 50 000 kbps). - Profile HDR mode —
ProfilePreferences,UpdateProfilePreferencesandProfilePreferenceDefaultscarryhdrMode(autoortoneMapToSdr).autokeeps passing HDR through where the device supports it;toneMapToSdralways converts HDR sources to SDR. - Backup code count —
auth.getBackupCodesStatus()forGET /auth/two-factor/backup-codes, typed byTwoFactorBackupCodesStatusSchema/TwoFactorBackupCodesStatus({ remaining: number | null }). - Rating badge preference —
hideRatingOverlayinProfilePreferencesSchema,UpdateProfilePreferencesSchemaandProfilePreferenceDefaultsSchema. It hides the rating badge on poster cards and defaults to off. - Catalog statuses —
metadata.getStatuses()forGET /metadata/statuses, withMetadataStatusesResponseSchema/MetadataStatusesResponse({ statuses: string[] }). - Dry runs for log cleanup and trickplay deletes —
admin.cleanupLogs(retentionDays, { dryRun })andadmin.deleteTrickplayMany(ids, { dryRun }).TrickplayDeleteResultand the log cleanup result carrydryRun; a dry run reports what would be removed and removes nothing. - Worker history purge dry run —
PurgeWorkerHistoryOptions.dryRunandPurgeWorkerHistoryResponse.dryRun; a dry run reports the counts a purge would delete and removes nothing. - Cancel an update —
admin.cancelUpdate(target)forPOST /admin/update/cancel.AdminUpdateCancelResponseSchema/AdminUpdateCancelResponsedescribe the reply, and an update history entry may now have statuscancelled. - Forced server updates —
admin.installUpdate(target, { force })andadmin.rollbackUpdate(target, { force }). A server install or rollback is refused withupdate.blocked_active_streamswhile streams play, unlessforceis set. - Plugin configuration reset, export and import —
admin.resetPluginConfig(id, { keys? }),admin.exportPluginConfig(id)andadmin.importPluginConfig(id, file)withResetPluginConfigBodySchemaandPluginConfigExportSchema. Exports never contain secret fields. - Catalog reports unavailable repositories —
admin.getPluginCatalog()returns{ plugins, unavailableRepositories }; each unavailable repository has itsrepositoryId,repositoryNameand anerrorCode.PluginCatalogResultSchema/PluginCatalogResultdescribe it. - Bulk plugin state and version pinning —
admin.setPluginsEnabled({ enabled, pluginIds })returns an outcome per plugin;admin.setPluginPinned(id, pinned);PluginAdminStatus.pinned. - Refuse a plugin's CSP sources —
PluginAdminStatus.cspDisabledandadmin.setPluginCsp(id, enabled)forPUT /admin/plugins/:id/csp. - Setting metadata —
SystemSettingItemViewreports theunitof a number setting andrestartRequiredfor settings that take effect only after a restart. - Server capabilities —
ServerCapabilitiesSchema/ServerCapabilitiesandreelvault.capabilities.get()for the publicGET /capabilitiesendpoint (trickplay, downloads). - Profile PIN status —
profiles.getPinStatus(id)returns{ hasPin }for the owner's profile (ProfilePinStatusSchema/ProfilePinStatus), so settings can offer removing the PIN without ever receiving it. - Filtered marker list —
media.getAllMarkers({ type, source, q, limit })narrows the admin marker list on the server;MediaMarkerFiltersSchema/MediaMarkerFiltersdescribe the filters. Calls without arguments behave as before. - Subtitle text search —
SubtitleFiltersSchematakesq(up to 200 characters);subtitles.getAll({ q })matches it against the label, the language and the media file id. - Safer database restore —
admin.restoreDatabase(fileName, { force? })sends the optionalforce, andAdminDatabaseRestoreResponsecarriespreRestoreBackup, the copy taken just before the swap. - Audit filter options —
admin.getAuditOptions()returns the resource types in the audit log and the administrators who wrote entries (AdminAuditOptionsSchema/AdminAuditOptions), for the filter dropdowns.nameis null when the account no longer exists. - User list filters —
admin.getUsers({ role, status })narrows the account list by role (adminoruser) and by status (activeorblocked), next to the search. - Download title link —
DownloadJob.metadataId(nullable, also onAdminDownloadJobSchema) names the title the download's media file belongs to, so a download can link to its title. - Watchlist auto-removal preference — profile preferences gain
watchlistAutoRemoveWatched(boolean, off by default). When it is on, a title leaves the watchlist once the profile has watched it. The field is part ofProfilePreferencesSchema,UpdateProfilePreferencesSchemaandProfilePreferenceDefaultsSchema. - Watch state controls —
me.resetPlaybackProgress(mediaFileId, { scope })takesscope:fileresets only that file,title(the default) resets every file of its title.me.setWatchStateBulk({ mediaFileIds, watched })marks up to 500 files watched or unwatched in one call (WatchStateBulkSchema/WatchStateBulk,WatchStateScopeSchema/WatchStateScope). - Update history and environment —
admin.getUpdateHistory({ page, limit })pages through the installs and rollbacks (AdminUpdateHistoryPageSchema/AdminUpdateHistoryPage).AdminUpdateStatus.environmentreports the container engine (docker,podmanor none), whether the server runs without root and whether systemd manages it as auserorsystemunit (AdminUpdateEnvironmentSchema). - Subtitle extractability —
Subtitle.extractableisfalsefor image-based embedded tracks (PGS, VobSub), which cannot be served as text. - Migration status —
admin.getDatabaseMigrations()returnsDatabaseMigrationStatus(total,applied,pending,latest,migrations). - Paginated marker list —
media.getAllMarkers(query)takespagenext tolimitand returnsPaginatedResponse<MediaMarker>(data,total,totalPages) instead of a bare array. - Mark all read by type —
notifications.markAllRead(type?)marks only the notifications of the given type when one is passed. - Live activity capacity —
AdminLiveActivityResponsegainscapacity({ limit, active }): the server-wide stream limit and the number of slots in use. - Remove notifications —
notifications.delete(id)andnotifications.deleteMany(ids)(up to 200) remove notifications from the caller's list and return{ deleted }. - Trickplay regeneration by scope —
admin.regenerateTrickplay({ scope, id, force? })(scopeislibrary,titleorseason) returnsTrickplayRegenerationQueued({ operationId?, matching, enqueued, remaining });admin.getTrickplayRegenerationReport(operationId)returnsTrickplayRegenerationReportwith the generated, budget-skipped, other-skipped, failed, cancelled and unfinished counts. - Worker schedule pause, job retry and watchdog state —
admin.setWorkerScheduleEnabled(workerId, enabled)returnsWorkerScheduleState({ workerId, enabled, nextRunAt });admin.retryWorkerJob(jobId)returnsWorkerRetryResponse({ success, jobId }of the new job);admin.getWorkerWatchdog()returnsWorkerWatchdogStatewithrecoveredJobsandlastRecoveredAt.WorkerSummarygainsscheduleEnabledand an optionalnextRunAt. - Worker job list —
admin.getWorkerJobs({ page, limit, workerId, status })returns one page of worker jobs (PaginatedResponse<WorkerJob>). - Watchlist bulk changes and clear —
me.bulkUpdateWatchlist({ add, remove })(WatchlistBulkBodySchema) andme.clearWatchlist(), withWatchlistBulkResponseandWatchlistClearResponse. - Log filters —
admin.getLogs({ module, exclude, from, to })takes the same filters as the server query. - Settings export and import —
admin.exportSystemSettings()(SystemSettingsExportSchema) andadmin.importSystemSettings(body)(ImportSystemSettingsSchema). - Resource history window —
admin.getResources({ hours })takes the history window in hours (1–168, default 24). - Audit search —
admin.getAudit({ q })matches one term against the resource id and the summary of each entry. - Download retry, cancel and quota —
downloads.retry(jobId)anddownloads.cancel(jobId);MyDownloadsResponseSchemacarriesquota(DownloadQuotaSchema). - Notification pages —
notifications.getPage({ page, limit, unreadOnly, type })returnsPaginatedResponse<Notification>. - Audit summary —
admin.getAuditSummary(query)returnsAdminAuditSummary: thetotaland oneactorsentry per administrator withtotal,creates,updates,deletes,lastAtandname. - Admin download list paging —
admin.getDownloadJobs({ page, limit, status })returns the page envelope withdata(previouslyjobs) andcountsper status. - Marker import —
media.importMarkers(ndjson)sends the NDJSON file as text/plain and returnsMarkerImportResult(mediaFilesandmarkersreplaced). - Setting change tracking —
SystemSettingItemViewcarriesupdatedAtandlastModifiedBy; the realtime event map hassettings:changed(keys,actorUserId,updatedAt). - API key rotation and editing —
admin.rotateApiKey(id)andadmin.updateApiKey(id, { name, expiresAtDays });ApiKeycarriescreatedByName. - Trickplay removal —
admin.deleteTrickplay(mediaFileId)andadmin.deleteTrickplayMany(mediaFileIds)returnTrickplayDeleteResultSchema;admin.getArtifactStats()reads the artifact rows per owner and kind. - Database integrity and optimize —
admin.getDatabaseIntegrity()(DatabaseIntegrity:okand the messages SQLite reports) andadmin.optimizeDatabase(). - Bulk stream termination —
admin.terminateLiveStreams({ sessionIds, reason })returnsBulkTerminateSessionsResult: theterminatedandfailedcounts and one result per session. - Change password —
auth.changePassword({ currentPassword, newPassword })withChangePasswordRequestSchema/ChangePasswordResponseSchema. Every other session is revoked while the current one stays signed in. - Subtitle language priority list —
subtitleFallbackLanguageson profile preferences and preference defaults: a comma-separated list (e.g.en,de) tried aftersubtitleLanguage. - Remove from Continue Watching —
me.dismissContinueWatching(metadataId)hides a title without discarding resume positions. - Rewind on resume —
resumeRewindSeconds(0–30) on profile preferences and preference defaults. - Plugin UI switches —
admin.getPluginUiSettings/updatePluginUiSettings/resetPluginUiSettingswithPluginUiSettingsSchemaandUpdatePluginUiSettingsBodySchema: list the switchable parts of a plugin's UI (pages, dialogs, tabs, slot entries, search provider, pre-roll) and hide them individually or all at once. - Liveness and readiness probes —
health.live()andhealth.ready()forGET /health/liveandGET /health/ready(HealthLiveResponseSchema). - Number setting bounds —
SystemSettingItemViewcarriesminandmaxfor number settings. - Stable slot entry ids —
PluginSlotContribution.id(optional) keys an entry in administrator interface switches, so the switch survives reordering and edits of the other entries in the same slot. - Plugin failure codes —
PluginRuntimeStatus.errorCode(optional) carries a stable code forerror:plugin.manifest_invalid,plugin.load_failed,plugin.already_installedor a domain code - Unreadable plugin configuration is visible —
PluginAdminStatus(returned by the admin plugin endpoints) carriesconfigReadError(plugin.config_unreadable) when a plugin'sconfig.jsonexists but cannot be read. Previously the plugin silently ran on its defaults. - Localized plugin config text —
label,descriptionand select option labels accept a locale map ({ en: "…", pl: "…" }) as well as plain text.PluginConfigFieldSchemaandPluginConfigFieldOptionSchemaaccept both forms, so the admin configuration endpoint can return either. - Secret presence in plugin configuration —
PluginConfigField.hasValue(optional) on secret fields tells whether a value is stored, so an interface can show "set" without ever receiving the secret. - Plugin package details —
PluginAdminStatusgainscapabilities(declared in the manifest),installedAt,source,integrityOk(package matched its recorded integrity at the last check) andupdateAvailable(an enabled catalog offers a newer version). - Plugin install outcome —
InstallCatalogPluginResponsereportspreviousVersion,direction(install/upgrade/downgrade/reinstall) andstate(enabled/disabled/rolled_back/failed), witherroranderrorCodewhen the new version did not load. An install no longer reports success while the plugin is not running. - Admin plugin client types —
admin.getPlugins(),enablePlugin(),disablePlugin(),reloadPlugin()andreloadPlugins()returnPluginAdminStatus, which carries the package details andconfigReadError. - Plugin archive dry run —
admin.validatePluginArchive(file)(POST /admin/plugins/validate) checks an uploaded archive without installing it and returnsvalid, the plugin id and version, the installed version, thedirectionof the change and theissues(severityerrororwarning, a stablecodeand a rawmessage). - Profile update accepts null —
UpdateProfileSchematakespin: null(remove the PIN) andavatarUrl: null(remove the avatar); omitted fields stay as they are. - Admin user sessions —
admin.getUserSessions(userId)lists a user's sessions that have not expired (AdminUserSessionsPage, never the token),admin.revokeUserSession(userId, sessionId)ends one, andadmin.revokeUsersSessions({ userIds })ends every session of up to 100 users, returningrevokedSessions.AdminUsercarrieslastActiveAtandactiveSessionCount. - Bulk refresh —
episodes.bulkRefresh(ids),people.bulkRefresh(ids)andmedia.bulkRefresh(ids)take up to 50 ids and returnBulkRefreshResult(results, one{ id, ok, code? }per id;codeis set only for a failed id). - Season download —
downloads.queueSeason({ seasonId, quality?, force? })forPOST /downloads/seasons, typed byQueueSeasonDownloadSchema/QueueSeasonDownloadandDownloadSeasonQueueResultSchema/DownloadSeasonQueueResult(results, one outcome per episode). - Library health and error-check results —
libraries.getHealth()forGET /libraries/health(LibraryHealthResponse: per library the last scan and each path'sexists,isDirectory,watchStatusandunwatchableCode), andlibraries.getErrorsCheckStatus(operationId)forGET /libraries/check-errors/:operationId(LibraryErrorsCheckStatus, whoseresultis set once the check has completed). - Bulk subtitle delete —
subtitles.bulkDelete(ids)forPOST /subtitles/bulk-delete, typed byBulkSubtitleDeleteSchema/BulkSubtitleDeleteResultSchema(one outcome per id). - Copy profile preferences —
profiles.copyPreferences(id, sourceProfileId)forPOST /profiles/:id/preferences/copy(CopyProfilePreferencesSchema);CreateProfiletakescopyPreferencesFromProfileId. - Muted notification types —
mutedNotificationTypes(comma-separated) inProfilePreferencesSchema,UpdateProfilePreferencesSchemaandProfilePreferenceDefaultsSchema. - Hidden menu pages —
hiddenPages(comma-separated) inProfilePreferencesSchema,UpdateProfilePreferencesSchemaandProfilePreferenceDefaultsSchema. - Bulk artwork refresh and image cache purge —
metadata.bulkRefreshImages(ids)forPOST /metadata/bulk-refresh-images(up to 50 titles, one{ id, ok, code? }result per id) andadmin.purgeImageCache()forPOST /admin/image-cache/purge, typed byImageCachePurgeResultSchema/ImageCachePurgeResult(removedFiles,freedBytes). - Database backup upload —
admin.uploadDatabaseBackup(file)posts a SQLite backup toPOST /admin/database/backups/uploadand returns the storedAdminDatabaseBackup. - Subtitle upload —
subtitles.upload({ mediaFileId, language, label?, file, fileName })posts an SRT, WebVTT or ASS file toPOST /subtitles/upload; the server returns the newSubtitle. - Bulk delete of media files and titles —
media.bulkDelete(ids, { force? })andmetadata.bulkDelete(ids, { force? })post up to 50 ids toPOST /media-files/bulk-deleteandPOST /metadata/bulk-delete, typed byBulkDeleteBodySchema/BulkDeleteResultSchema(one{ id, ok, code? }result per id). A file or title a stream is playing is held back withmedia.delete_blocked_active_streamsormetadata.delete_blocked_active_streamsunlessforceis set. - Subtitle provider switch —
SubtitleProviderInfoSchema(a subtitle provider withenabled) forGET /subtitles/providers, andsubtitles.setProviderEnabled(providerId, enabled)forPATCH /subtitles/providers/:providerId(admin). - Playback sessions —
playbackSessions.releaseMine()ends every session of the calling profile (DELETE /playback-sessions/mine).PlaybackSessionSummarygainspositionSecondsandpaused, andPlaybackSessiongainsheartbeatIntervalMs. - Plugin validation issue parameters —
PluginValidationIssuecarries an optionalparamsnext tocode: the values the translation of the code interpolates, such as the invalid field. A client can name the exact problem in each issue of a plugin archive check.