@memberjunction/ng-media-player 0.0.1 → 5.44.0
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/README.md +241 -28
- package/dist/lib/media-player/cue-utils.d.ts +24 -0
- package/dist/lib/media-player/cue-utils.d.ts.map +1 -0
- package/dist/lib/media-player/cue-utils.js +47 -0
- package/dist/lib/media-player/cue-utils.js.map +1 -0
- package/dist/lib/media-player/media-player.component.d.ts +326 -0
- package/dist/lib/media-player/media-player.component.d.ts.map +1 -0
- package/dist/lib/media-player/media-player.component.js +1545 -0
- package/dist/lib/media-player/media-player.component.js.map +1 -0
- package/dist/lib/media-player/playback-state.d.ts +46 -0
- package/dist/lib/media-player/playback-state.d.ts.map +1 -0
- package/dist/lib/media-player/playback-state.js +86 -0
- package/dist/lib/media-player/playback-state.js.map +1 -0
- package/dist/lib/media-player/transcript-layout.d.ts +35 -0
- package/dist/lib/media-player/transcript-layout.d.ts.map +1 -0
- package/dist/lib/media-player/transcript-layout.js +37 -0
- package/dist/lib/media-player/transcript-layout.js.map +1 -0
- package/dist/lib/media-player/waveform-utils.d.ts +45 -0
- package/dist/lib/media-player/waveform-utils.d.ts.map +1 -0
- package/dist/lib/media-player/waveform-utils.js +108 -0
- package/dist/lib/media-player/waveform-utils.js.map +1 -0
- package/dist/lib/media-player.types.d.ts +107 -0
- package/dist/lib/media-player.types.d.ts.map +1 -0
- package/dist/lib/media-player.types.js +9 -0
- package/dist/lib/media-player.types.js.map +1 -0
- package/dist/lib/storage-media-player/storage-media-player.component.d.ts +77 -0
- package/dist/lib/storage-media-player/storage-media-player.component.d.ts.map +1 -0
- package/dist/lib/storage-media-player/storage-media-player.component.js +283 -0
- package/dist/lib/storage-media-player/storage-media-player.component.js.map +1 -0
- package/dist/public-api.d.ts +8 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +11 -0
- package/dist/public-api.js.map +1 -0
- package/package.json +36 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-media-player.component.js","sourceRoot":"","sources":["../../../src/lib/storage-media-player/storage-media-player.component.ts","../../../src/lib/storage-media-player/storage-media-player.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Input,\n OnInit,\n inject,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { LogError } from '@memberjunction/core';\nimport { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MJMediaPlayerComponent } from '../media-player/media-player.component';\nimport { MediaTrack, MediaTranscriptCue } from '../media-player.types';\n\n/** Shape of the `CreateMediaAccessToken` server mutation result (one file). */\ninterface CreateMediaAccessTokenResult {\n Success: boolean;\n Token?: string | null;\n Url?: string | null;\n ExpiresAt?: string | null;\n MimeType?: string | null;\n /**\n * Optional precomputed waveform peaks (normalized `0..1`, one per bar) read from a `peaks.json`\n * sidecar beside the file. When present, the player renders the real waveform instantly with NO\n * client-side fetch/decode of the audio. Absent → the player falls back to client-side extraction.\n */\n Peaks?: number[] | null;\n ErrorMessage?: string | null;\n}\n\n/**\n * The exact GraphQL mutation this wrapper consumes. Mints a short-lived signed token (after a\n * server-side per-user permission check) and returns the authenticated `/media/<fileId>?token=`\n * streaming URL — which `<audio>`/`<video>` stream natively with HTTP Range (seek-before-download).\n */\nconst CREATE_MEDIA_ACCESS_TOKEN_MUTATION = `mutation CreateMediaAccessToken($fileId: String!) {\n CreateMediaAccessToken(fileId: $fileId) {\n Success\n Url\n ExpiresAt\n MimeType\n Peaks\n ErrorMessage\n }\n}`;\n\n/**\n * `mj-storage-media-player` — an MJStorage-bound wrapper around {@link MJMediaPlayerComponent}.\n *\n * Resolves one or more MJ Storage file IDs into playable {@link MediaTrack}s by minting a\n * short-lived authenticated streaming URL per file via the `CreateMediaAccessToken` GraphQL\n * mutation, and handing those URLs to the generic player. The `<audio>`/`<video>` element\n * streams each URL natively over HTTP Range (progressive playback + seek-before-download for\n * large video) instead of base64'ing the whole file over GraphQL. Surfaces graceful loading /\n * no-access / empty states.\n *\n * Waveform peaks: when the recording has a `peaks.json` sidecar in storage, `CreateMediaAccessToken`\n * returns precomputed peaks and this wrapper sets them on the {@link MediaTrack.Peaks}, so the player\n * renders the real waveform instantly with NO client-side fetch/decode. When no sidecar exists, audio\n * waveforms still decode client-side via the streaming URL (the waveform's one-time `fetch(Url)`\n * issues a no-Range GET, which returns the full file — fine for audio). Video shows the progress bar.\n */\n@Component({\n selector: 'mj-storage-media-player',\n standalone: true,\n imports: [CommonModule, MJMediaPlayerComponent],\n templateUrl: './storage-media-player.component.html',\n styleUrls: ['./storage-media-player.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class MJStorageMediaPlayerComponent extends BaseAngularComponent implements OnInit {\n private cdr = inject(ChangeDetectorRef);\n\n // ---------------------------------------------------------------------------\n // Inputs — file resolution\n // ---------------------------------------------------------------------------\n\n /** Convenience single-file id. Combined with {@link FileIDs}; duplicates are de-duped. */\n @Input()\n set FileID(value: string | null) {\n if (value !== this._fileID) {\n this._fileID = value;\n if (this._initialized) {\n void this.resolveTracks();\n }\n }\n }\n get FileID(): string | null {\n return this._fileID;\n }\n private _fileID: string | null = null;\n\n /** Multi-track file ids (e.g. separate meeting streams). */\n @Input()\n set FileIDs(value: string[]) {\n const next = value ?? [];\n if (!this.sameIds(next, this._fileIDs)) {\n this._fileIDs = next;\n if (this._initialized) {\n void this.resolveTracks();\n }\n }\n }\n get FileIDs(): string[] {\n return this._fileIDs;\n }\n private _fileIDs: string[] = [];\n\n /** Transcript cues forwarded to the generic player. */\n @Input() Transcript: MediaTranscriptCue[] | null = null;\n\n // ---------------------------------------------------------------------------\n // Inputs — pass-through feature flags (forwarded to the generic player)\n // ---------------------------------------------------------------------------\n\n @Input() ShowTranscript = true;\n /** Whether the transcript show/hide toggle button renders. Forwarded to the generic player. */\n @Input() ShowTranscriptToggle = true;\n @Input() ShowSpeedControl = true;\n @Input() ShowSkipControls = true;\n @Input() ShowVolume = true;\n /**\n * Forwarded to the generic player. On by default — the streaming URL is same-origin (served by\n * MJAPI) and a no-Range GET returns the full file, so client-side peak extraction decodes cleanly.\n */\n @Input() ShowWaveform = true;\n @Input() ShowFullscreen = true;\n @Input() SkipSeconds = 30;\n @Input() PlaybackRates: number[] = [0.5, 1, 1.25, 1.5, 2];\n @Input() Autoplay = false;\n @Input() StartAtMs: number | null = null;\n /** Where the transcript sits. Defaults to `'bottom'` (matches the generic player). */\n @Input() TranscriptPosition: 'side' | 'bottom' = 'bottom';\n\n // ---------------------------------------------------------------------------\n // State\n // ---------------------------------------------------------------------------\n\n private _initialized = false;\n private _resolvedTracks: MediaTrack[] = [];\n private _isLoading = false;\n private _accessError: string | null = null;\n private _resolveToken = 0;\n\n get ResolvedTracks(): MediaTrack[] {\n return this._resolvedTracks;\n }\n get IsLoading(): boolean {\n return this._isLoading;\n }\n get AccessError(): string | null {\n return this._accessError;\n }\n get HasFileIds(): boolean {\n return this.collectFileIds().length > 0;\n }\n\n async ngOnInit(): Promise<void> {\n this._initialized = true;\n await this.resolveTracks();\n }\n\n // ---------------------------------------------------------------------------\n // Resolution\n // ---------------------------------------------------------------------------\n\n /** Resolves all configured file ids into playable streaming tracks. Re-entrant-safe via a token. */\n private async resolveTracks(): Promise<void> {\n const ids = this.collectFileIds();\n const token = ++this._resolveToken;\n\n // start fresh\n this._resolvedTracks = [];\n this._accessError = null;\n\n if (ids.length === 0) {\n this._isLoading = false;\n this.cdr.markForCheck();\n return;\n }\n\n this._isLoading = true;\n this.cdr.markForCheck();\n\n const tracks: MediaTrack[] = [];\n let firstError: string | null = null;\n\n for (const id of ids) {\n const result = await this.mintAccessToken(id);\n if (token !== this._resolveToken) {\n return; // a newer resolution superseded this one\n }\n if (result && result.Success && result.Url) {\n tracks.push(this.buildTrack(id, result.Url, result.MimeType ?? null, result.Peaks ?? null));\n } else if (!firstError) {\n firstError = result?.ErrorMessage || 'This recording is not available.';\n }\n }\n\n if (token !== this._resolveToken) {\n return;\n }\n\n this._resolvedTracks = tracks;\n // Only surface the no-access state when NOTHING resolved.\n this._accessError = tracks.length === 0 ? firstError : null;\n this._isLoading = false;\n this.cdr.markForCheck();\n }\n\n /** Mints an authenticated streaming-URL token for one file id via the active provider. */\n private async mintAccessToken(fileId: string): Promise<CreateMediaAccessTokenResult | null> {\n try {\n const provider = this.ProviderToUse as unknown as GraphQLDataProvider;\n const data = await provider.ExecuteGQL(CREATE_MEDIA_ACCESS_TOKEN_MUTATION, { fileId });\n const payload = data?.CreateMediaAccessToken as CreateMediaAccessTokenResult | undefined;\n return payload ?? null;\n } catch (err) {\n LogError(`CreateMediaAccessToken failed for file '${fileId}': ${err instanceof Error ? err.message : String(err)}`);\n return { Success: false, ErrorMessage: 'Unable to load this recording.' };\n }\n }\n\n /**\n * Builds a MediaTrack from the streaming URL. Kind is MIME-derived (defaults to audio). When the\n * server supplied precomputed waveform `peaks` (from a peaks.json sidecar), they're attached so the\n * player renders the real waveform instantly with NO extra fetch/decode; otherwise the player\n * extracts peaks client-side from the streaming URL.\n */\n private buildTrack(fileId: string, url: string, mimeType: string | null, peaks: number[] | null): MediaTrack {\n const mime = mimeType || undefined;\n const track: MediaTrack = {\n Id: fileId,\n Kind: mime && mime.startsWith('video') ? 'video' : 'audio',\n Url: url,\n MimeType: mime,\n };\n if (Array.isArray(peaks) && peaks.length > 0) {\n track.Peaks = peaks;\n }\n return track;\n }\n\n private collectFileIds(): string[] {\n const ids: string[] = [];\n if (this._fileID) {\n ids.push(this._fileID);\n }\n for (const id of this._fileIDs) {\n if (id && !ids.includes(id)) {\n ids.push(id);\n }\n }\n return ids;\n }\n\n private sameIds(a: string[], b: string[]): boolean {\n if (a.length !== b.length) {\n return false;\n }\n return a.every((v, i) => v === b[i]);\n }\n}\n","@if (IsLoading) {\n <div class=\"mj-storage-media-state\" role=\"status\" aria-live=\"polite\">\n <i class=\"fa-solid fa-circle-notch fa-spin mj-storage-media-state__icon\" aria-hidden=\"true\"></i>\n <span>Loading recording…</span>\n </div>\n} @else if (AccessError) {\n <div class=\"mj-storage-media-state mj-storage-media-state--error\" role=\"alert\">\n <i class=\"fa-solid fa-lock mj-storage-media-state__icon\" aria-hidden=\"true\"></i>\n <div class=\"mj-storage-media-state__body\">\n <span class=\"mj-storage-media-state__title\">This recording isn't available — you may not have access.</span>\n <span class=\"mj-storage-media-state__detail\">{{ AccessError }}</span>\n </div>\n </div>\n} @else if (!HasFileIds || ResolvedTracks.length === 0) {\n <div class=\"mj-storage-media-state\" role=\"status\">\n <i class=\"fa-solid fa-film mj-storage-media-state__icon\" aria-hidden=\"true\"></i>\n <span>No recording to play.</span>\n </div>\n} @else {\n <mj-media-player\n [Tracks]=\"ResolvedTracks\"\n [Transcript]=\"Transcript\"\n [ShowTranscript]=\"ShowTranscript\"\n [ShowTranscriptToggle]=\"ShowTranscriptToggle\"\n [ShowSpeedControl]=\"ShowSpeedControl\"\n [ShowSkipControls]=\"ShowSkipControls\"\n [ShowVolume]=\"ShowVolume\"\n [ShowWaveform]=\"ShowWaveform\"\n [ShowFullscreen]=\"ShowFullscreen\"\n [SkipSeconds]=\"SkipSeconds\"\n [PlaybackRates]=\"PlaybackRates\"\n [Autoplay]=\"Autoplay\"\n [StartAtMs]=\"StartAtMs\"\n [TranscriptPosition]=\"TranscriptPosition\"\n ></mj-media-player>\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './lib/media-player.types';
|
|
2
|
+
export * from './lib/media-player/cue-utils';
|
|
3
|
+
export * from './lib/media-player/playback-state';
|
|
4
|
+
export * from './lib/media-player/transcript-layout';
|
|
5
|
+
export * from './lib/media-player/waveform-utils';
|
|
6
|
+
export * from './lib/media-player/media-player.component';
|
|
7
|
+
export * from './lib/storage-media-player/storage-media-player.component';
|
|
8
|
+
//# sourceMappingURL=public-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAIA,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAClD,cAAc,sCAAsC,CAAC;AACrD,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2DAA2D,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Public API Surface — @memberjunction/ng-media-player
|
|
3
|
+
*/
|
|
4
|
+
export * from './lib/media-player.types';
|
|
5
|
+
export * from './lib/media-player/cue-utils';
|
|
6
|
+
export * from './lib/media-player/playback-state';
|
|
7
|
+
export * from './lib/media-player/transcript-layout';
|
|
8
|
+
export * from './lib/media-player/waveform-utils';
|
|
9
|
+
export * from './lib/media-player/media-player.component';
|
|
10
|
+
export * from './lib/storage-media-player/storage-media-player.component';
|
|
11
|
+
//# sourceMappingURL=public-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAClD,cAAc,sCAAsC,CAAC;AACrD,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2DAA2D,CAAC","sourcesContent":["/*\n * Public API Surface — @memberjunction/ng-media-player\n */\n\nexport * from './lib/media-player.types';\nexport * from './lib/media-player/cue-utils';\nexport * from './lib/media-player/playback-state';\nexport * from './lib/media-player/transcript-layout';\nexport * from './lib/media-player/waveform-utils';\nexport * from './lib/media-player/media-player.component';\nexport * from './lib/storage-media-player/storage-media-player.component';\n"]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-media-player",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
]
|
|
3
|
+
"version": "5.44.0",
|
|
4
|
+
"description": "World-class generic media (audio/video) player with transcript sync, plus an MJStorage-bound wrapper.",
|
|
5
|
+
"main": "./dist/public-api.js",
|
|
6
|
+
"typings": "./dist/public-api.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"/dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "vitest run",
|
|
12
|
+
"build": "ngc",
|
|
13
|
+
"test:watch": "vitest"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [],
|
|
16
|
+
"author": "",
|
|
17
|
+
"license": "ISC",
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@angular/compiler": "21.1.3",
|
|
20
|
+
"@angular/compiler-cli": "21.1.3",
|
|
21
|
+
"@memberjunction/ng-test-utils": "5.44.0",
|
|
22
|
+
"vitest": "^4.0.18"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"@angular/common": "21.1.3",
|
|
26
|
+
"@angular/core": "21.1.3"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"tslib": "^2.8.1",
|
|
30
|
+
"@memberjunction/core": "5.44.0",
|
|
31
|
+
"@memberjunction/graphql-dataprovider": "5.44.0",
|
|
32
|
+
"@memberjunction/ng-base-types": "5.44.0"
|
|
33
|
+
},
|
|
34
|
+
"sideEffects": false,
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "https://github.com/MemberJunction/MJ"
|
|
38
|
+
}
|
|
10
39
|
}
|