@banou/media-player 0.4.6 → 0.5.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.
@@ -1,4 +1,4 @@
1
- import type { Attachment, SubtitleFragment } from 'libav-wasm/build/worker';
1
+ import type { Attachment, Index, SubtitleFragment } from 'libav-wasm/build/worker';
2
2
  import { makeRemuxer } from 'libav-wasm';
3
3
  import { MediaSourceOptions } from './media-source';
4
4
  import { SubtitleStream } from './subtitles';
@@ -23,6 +23,7 @@ declare const _default: import("xstate").StateMachine<{
23
23
  subtitleFragments: SubtitleFragment[];
24
24
  subtitleStreams: SubtitleStream[];
25
25
  selectedSubtitleStreamIndex: number | undefined;
26
+ indexes: Index[];
26
27
  thumbnails: Thumbnail[];
27
28
  isReady: boolean;
28
29
  }, {
@@ -433,6 +434,7 @@ declare const _default: import("xstate").StateMachine<{
433
434
  readonly subtitleFragments: [];
434
435
  readonly subtitleStreams: [];
435
436
  readonly selectedSubtitleStreamIndex: undefined;
437
+ readonly indexes: [];
436
438
  readonly thumbnails: [];
437
439
  readonly isReady: false;
438
440
  };
@@ -457,6 +459,7 @@ declare const _default: import("xstate").StateMachine<{
457
459
  subtitleFragments: SubtitleFragment[];
458
460
  subtitleStreams: SubtitleStream[];
459
461
  selectedSubtitleStreamIndex: number | undefined;
462
+ indexes: Index[];
460
463
  thumbnails: Thumbnail[];
461
464
  isReady: boolean;
462
465
  }, {
@@ -733,6 +736,7 @@ declare const _default: import("xstate").StateMachine<{
733
736
  subtitleFragments: SubtitleFragment[];
734
737
  subtitleStreams: SubtitleStream[];
735
738
  selectedSubtitleStreamIndex: number | undefined;
739
+ indexes: Index[];
736
740
  thumbnails: Thumbnail[];
737
741
  isReady: boolean;
738
742
  }, {
@@ -1010,6 +1014,7 @@ declare const _default: import("xstate").StateMachine<{
1010
1014
  subtitleFragments: SubtitleFragment[];
1011
1015
  subtitleStreams: SubtitleStream[];
1012
1016
  selectedSubtitleStreamIndex: number | undefined;
1017
+ indexes: Index[];
1013
1018
  thumbnails: Thumbnail[];
1014
1019
  isReady: boolean;
1015
1020
  }, {
@@ -1287,6 +1292,7 @@ declare const _default: import("xstate").StateMachine<{
1287
1292
  subtitleFragments: SubtitleFragment[];
1288
1293
  subtitleStreams: SubtitleStream[];
1289
1294
  selectedSubtitleStreamIndex: number | undefined;
1295
+ indexes: Index[];
1290
1296
  thumbnails: Thumbnail[];
1291
1297
  isReady: boolean;
1292
1298
  }, {
@@ -1563,6 +1569,7 @@ declare const _default: import("xstate").StateMachine<{
1563
1569
  subtitleFragments: SubtitleFragment[];
1564
1570
  subtitleStreams: SubtitleStream[];
1565
1571
  selectedSubtitleStreamIndex: number | undefined;
1572
+ indexes: Index[];
1566
1573
  thumbnails: Thumbnail[];
1567
1574
  isReady: boolean;
1568
1575
  }, {
@@ -1839,6 +1846,7 @@ declare const _default: import("xstate").StateMachine<{
1839
1846
  subtitleFragments: SubtitleFragment[];
1840
1847
  subtitleStreams: SubtitleStream[];
1841
1848
  selectedSubtitleStreamIndex: number | undefined;
1849
+ indexes: Index[];
1842
1850
  thumbnails: Thumbnail[];
1843
1851
  isReady: boolean;
1844
1852
  }, {
@@ -2122,6 +2130,7 @@ declare const _default: import("xstate").StateMachine<{
2122
2130
  subtitleFragments: SubtitleFragment[];
2123
2131
  subtitleStreams: SubtitleStream[];
2124
2132
  selectedSubtitleStreamIndex: number | undefined;
2133
+ indexes: Index[];
2125
2134
  thumbnails: Thumbnail[];
2126
2135
  isReady: boolean;
2127
2136
  };
@@ -2230,6 +2239,7 @@ declare const _default: import("xstate").StateMachine<{
2230
2239
  subtitleFragments: SubtitleFragment[];
2231
2240
  subtitleStreams: SubtitleStream[];
2232
2241
  selectedSubtitleStreamIndex: number | undefined;
2242
+ indexes: Index[];
2233
2243
  thumbnails: Thumbnail[];
2234
2244
  isReady: boolean;
2235
2245
  }, {
@@ -2431,6 +2441,7 @@ declare const _default: import("xstate").StateMachine<{
2431
2441
  subtitleFragments: SubtitleFragment[];
2432
2442
  subtitleStreams: SubtitleStream[];
2433
2443
  selectedSubtitleStreamIndex: number | undefined;
2444
+ indexes: Index[];
2434
2445
  thumbnails: Thumbnail[];
2435
2446
  isReady: boolean;
2436
2447
  };
@@ -2539,6 +2550,7 @@ declare const _default: import("xstate").StateMachine<{
2539
2550
  subtitleFragments: SubtitleFragment[];
2540
2551
  subtitleStreams: SubtitleStream[];
2541
2552
  selectedSubtitleStreamIndex: number | undefined;
2553
+ indexes: Index[];
2542
2554
  thumbnails: Thumbnail[];
2543
2555
  isReady: boolean;
2544
2556
  }, {
@@ -2740,6 +2752,7 @@ declare const _default: import("xstate").StateMachine<{
2740
2752
  subtitleFragments: SubtitleFragment[];
2741
2753
  subtitleStreams: SubtitleStream[];
2742
2754
  selectedSubtitleStreamIndex: number | undefined;
2755
+ indexes: Index[];
2743
2756
  thumbnails: Thumbnail[];
2744
2757
  isReady: boolean;
2745
2758
  };
@@ -2848,6 +2861,7 @@ declare const _default: import("xstate").StateMachine<{
2848
2861
  subtitleFragments: SubtitleFragment[];
2849
2862
  subtitleStreams: SubtitleStream[];
2850
2863
  selectedSubtitleStreamIndex: number | undefined;
2864
+ indexes: Index[];
2851
2865
  thumbnails: Thumbnail[];
2852
2866
  isReady: boolean;
2853
2867
  }, {
@@ -3048,6 +3062,7 @@ declare const _default: import("xstate").StateMachine<{
3048
3062
  subtitleFragments: SubtitleFragment[];
3049
3063
  subtitleStreams: SubtitleStream[];
3050
3064
  selectedSubtitleStreamIndex: number | undefined;
3065
+ indexes: Index[];
3051
3066
  thumbnails: Thumbnail[];
3052
3067
  isReady: boolean;
3053
3068
  };
@@ -3156,6 +3171,7 @@ declare const _default: import("xstate").StateMachine<{
3156
3171
  subtitleFragments: SubtitleFragment[];
3157
3172
  subtitleStreams: SubtitleStream[];
3158
3173
  selectedSubtitleStreamIndex: number | undefined;
3174
+ indexes: Index[];
3159
3175
  thumbnails: Thumbnail[];
3160
3176
  isReady: boolean;
3161
3177
  }, {
@@ -3356,6 +3372,7 @@ declare const _default: import("xstate").StateMachine<{
3356
3372
  subtitleFragments: SubtitleFragment[];
3357
3373
  subtitleStreams: SubtitleStream[];
3358
3374
  selectedSubtitleStreamIndex: number | undefined;
3375
+ indexes: Index[];
3359
3376
  thumbnails: Thumbnail[];
3360
3377
  isReady: boolean;
3361
3378
  };
@@ -3464,6 +3481,7 @@ declare const _default: import("xstate").StateMachine<{
3464
3481
  subtitleFragments: SubtitleFragment[];
3465
3482
  subtitleStreams: SubtitleStream[];
3466
3483
  selectedSubtitleStreamIndex: number | undefined;
3484
+ indexes: Index[];
3467
3485
  thumbnails: Thumbnail[];
3468
3486
  isReady: boolean;
3469
3487
  }, {
@@ -3666,6 +3684,7 @@ declare const _default: import("xstate").StateMachine<{
3666
3684
  subtitleFragments: SubtitleFragment[];
3667
3685
  subtitleStreams: SubtitleStream[];
3668
3686
  selectedSubtitleStreamIndex: number | undefined;
3687
+ indexes: Index[];
3669
3688
  thumbnails: Thumbnail[];
3670
3689
  isReady: boolean;
3671
3690
  }, {
@@ -3777,6 +3796,7 @@ declare const _default: import("xstate").StateMachine<{
3777
3796
  subtitleFragments: SubtitleFragment[];
3778
3797
  subtitleStreams: SubtitleStream[];
3779
3798
  selectedSubtitleStreamIndex: number | undefined;
3799
+ indexes: Index[];
3780
3800
  thumbnails: Thumbnail[];
3781
3801
  isReady: boolean;
3782
3802
  }, {
@@ -3888,6 +3908,7 @@ declare const _default: import("xstate").StateMachine<{
3888
3908
  subtitleFragments: SubtitleFragment[];
3889
3909
  subtitleStreams: SubtitleStream[];
3890
3910
  selectedSubtitleStreamIndex: number | undefined;
3911
+ indexes: Index[];
3891
3912
  thumbnails: Thumbnail[];
3892
3913
  isReady: boolean;
3893
3914
  }, {
@@ -4000,6 +4021,7 @@ declare const _default: import("xstate").StateMachine<{
4000
4021
  subtitleFragments: SubtitleFragment[];
4001
4022
  subtitleStreams: SubtitleStream[];
4002
4023
  selectedSubtitleStreamIndex: number | undefined;
4024
+ indexes: Index[];
4003
4025
  thumbnails: Thumbnail[];
4004
4026
  isReady: boolean;
4005
4027
  }, {
@@ -4112,6 +4134,7 @@ declare const _default: import("xstate").StateMachine<{
4112
4134
  subtitleFragments: SubtitleFragment[];
4113
4135
  subtitleStreams: SubtitleStream[];
4114
4136
  selectedSubtitleStreamIndex: number | undefined;
4137
+ indexes: Index[];
4115
4138
  thumbnails: Thumbnail[];
4116
4139
  isReady: boolean;
4117
4140
  }, {
@@ -4385,6 +4408,7 @@ declare const _default: import("xstate").StateMachine<{
4385
4408
  subtitleFragments: SubtitleFragment[];
4386
4409
  subtitleStreams: SubtitleStream[];
4387
4410
  selectedSubtitleStreamIndex: number | undefined;
4411
+ indexes: Index[];
4388
4412
  thumbnails: Thumbnail[];
4389
4413
  isReady: boolean;
4390
4414
  }, {
@@ -4658,6 +4682,7 @@ declare const _default: import("xstate").StateMachine<{
4658
4682
  subtitleFragments: SubtitleFragment[];
4659
4683
  subtitleStreams: SubtitleStream[];
4660
4684
  selectedSubtitleStreamIndex: number | undefined;
4685
+ indexes: Index[];
4661
4686
  thumbnails: Thumbnail[];
4662
4687
  isReady: boolean;
4663
4688
  }, {
@@ -4931,6 +4956,7 @@ declare const _default: import("xstate").StateMachine<{
4931
4956
  subtitleFragments: SubtitleFragment[];
4932
4957
  subtitleStreams: SubtitleStream[];
4933
4958
  selectedSubtitleStreamIndex: number | undefined;
4959
+ indexes: Index[];
4934
4960
  thumbnails: Thumbnail[];
4935
4961
  isReady: boolean;
4936
4962
  }, {
@@ -5205,6 +5231,7 @@ declare const _default: import("xstate").StateMachine<{
5205
5231
  subtitleFragments: SubtitleFragment[];
5206
5232
  subtitleStreams: SubtitleStream[];
5207
5233
  selectedSubtitleStreamIndex: number | undefined;
5234
+ indexes: Index[];
5208
5235
  thumbnails: Thumbnail[];
5209
5236
  isReady: boolean;
5210
5237
  }, {
@@ -5480,6 +5507,7 @@ declare const _default: import("xstate").StateMachine<{
5480
5507
  subtitleFragments: SubtitleFragment[];
5481
5508
  subtitleStreams: SubtitleStream[];
5482
5509
  selectedSubtitleStreamIndex: number | undefined;
5510
+ indexes: Index[];
5483
5511
  thumbnails: Thumbnail[];
5484
5512
  isReady: boolean;
5485
5513
  }, {
@@ -5593,6 +5621,7 @@ declare const _default: import("xstate").StateMachine<{
5593
5621
  subtitleFragments: SubtitleFragment[];
5594
5622
  subtitleStreams: SubtitleStream[];
5595
5623
  selectedSubtitleStreamIndex: number | undefined;
5624
+ indexes: Index[];
5596
5625
  thumbnails: Thumbnail[];
5597
5626
  isReady: boolean;
5598
5627
  }, {
@@ -5867,6 +5896,7 @@ declare const _default: import("xstate").StateMachine<{
5867
5896
  subtitleFragments: SubtitleFragment[];
5868
5897
  subtitleStreams: SubtitleStream[];
5869
5898
  selectedSubtitleStreamIndex: number | undefined;
5899
+ indexes: Index[];
5870
5900
  thumbnails: Thumbnail[];
5871
5901
  isReady: boolean;
5872
5902
  }, {
@@ -6141,6 +6171,7 @@ declare const _default: import("xstate").StateMachine<{
6141
6171
  subtitleFragments: SubtitleFragment[];
6142
6172
  subtitleStreams: SubtitleStream[];
6143
6173
  selectedSubtitleStreamIndex: number | undefined;
6174
+ indexes: Index[];
6144
6175
  thumbnails: Thumbnail[];
6145
6176
  isReady: boolean;
6146
6177
  }, {
@@ -6252,6 +6283,7 @@ declare const _default: import("xstate").StateMachine<{
6252
6283
  subtitleFragments: SubtitleFragment[];
6253
6284
  subtitleStreams: SubtitleStream[];
6254
6285
  selectedSubtitleStreamIndex: number | undefined;
6286
+ indexes: Index[];
6255
6287
  thumbnails: Thumbnail[];
6256
6288
  isReady: boolean;
6257
6289
  }, {
@@ -6366,6 +6398,7 @@ declare const _default: import("xstate").StateMachine<{
6366
6398
  subtitleFragments: SubtitleFragment[];
6367
6399
  subtitleStreams: SubtitleStream[];
6368
6400
  selectedSubtitleStreamIndex: number | undefined;
6401
+ indexes: Index[];
6369
6402
  thumbnails: Thumbnail[];
6370
6403
  isReady: boolean;
6371
6404
  }, {
@@ -6478,6 +6511,7 @@ declare const _default: import("xstate").StateMachine<{
6478
6511
  subtitleFragments: SubtitleFragment[];
6479
6512
  subtitleStreams: SubtitleStream[];
6480
6513
  selectedSubtitleStreamIndex: number | undefined;
6514
+ indexes: Index[];
6481
6515
  thumbnails: Thumbnail[];
6482
6516
  isReady: boolean;
6483
6517
  }, {
@@ -6590,6 +6624,7 @@ declare const _default: import("xstate").StateMachine<{
6590
6624
  subtitleFragments: SubtitleFragment[];
6591
6625
  subtitleStreams: SubtitleStream[];
6592
6626
  selectedSubtitleStreamIndex: number | undefined;
6627
+ indexes: Index[];
6593
6628
  thumbnails: Thumbnail[];
6594
6629
  isReady: boolean;
6595
6630
  }, {
@@ -6702,6 +6737,7 @@ declare const _default: import("xstate").StateMachine<{
6702
6737
  subtitleFragments: SubtitleFragment[];
6703
6738
  subtitleStreams: SubtitleStream[];
6704
6739
  selectedSubtitleStreamIndex: number | undefined;
6740
+ indexes: Index[];
6705
6741
  thumbnails: Thumbnail[];
6706
6742
  isReady: boolean;
6707
6743
  }, {
@@ -6976,6 +7012,7 @@ declare const _default: import("xstate").StateMachine<{
6976
7012
  subtitleFragments: SubtitleFragment[];
6977
7013
  subtitleStreams: SubtitleStream[];
6978
7014
  selectedSubtitleStreamIndex: number | undefined;
7015
+ indexes: Index[];
6979
7016
  thumbnails: Thumbnail[];
6980
7017
  isReady: boolean;
6981
7018
  }, {
@@ -7069,6 +7106,9 @@ declare const _default: import("xstate").StateMachine<{
7069
7106
  type: "DESTROY";
7070
7107
  }, undefined, never, never, never, never, never>;
7071
7108
  };
7109
+ readonly INDEXES: {
7110
+ readonly actions: readonly [import("xstate").ActionFunction<import("xstate").MachineContext, import("xstate").AnyEventObject, import("xstate").EventObject, import("xstate").NonReducibleUnknown, import("xstate").ProvidedActor, never, never, never, never>];
7111
+ };
7072
7112
  readonly NEW_ATTACHMENTS: {
7073
7113
  readonly actions: readonly [import("xstate").ActionFunction<{
7074
7114
  mediaSourceOptions: MediaSourceOptions | undefined;
@@ -7088,6 +7128,7 @@ declare const _default: import("xstate").StateMachine<{
7088
7128
  subtitleFragments: SubtitleFragment[];
7089
7129
  subtitleStreams: SubtitleStream[];
7090
7130
  selectedSubtitleStreamIndex: number | undefined;
7131
+ indexes: Index[];
7091
7132
  thumbnails: Thumbnail[];
7092
7133
  isReady: boolean;
7093
7134
  }, {
@@ -7359,6 +7400,7 @@ declare const _default: import("xstate").StateMachine<{
7359
7400
  subtitleFragments: SubtitleFragment[];
7360
7401
  subtitleStreams: SubtitleStream[];
7361
7402
  selectedSubtitleStreamIndex: number | undefined;
7403
+ indexes: Index[];
7362
7404
  thumbnails: Thumbnail[];
7363
7405
  isReady: boolean;
7364
7406
  }, {
@@ -7471,6 +7513,7 @@ declare const _default: import("xstate").StateMachine<{
7471
7513
  subtitleFragments: SubtitleFragment[];
7472
7514
  subtitleStreams: SubtitleStream[];
7473
7515
  selectedSubtitleStreamIndex: number | undefined;
7516
+ indexes: Index[];
7474
7517
  thumbnails: Thumbnail[];
7475
7518
  isReady: boolean;
7476
7519
  }, {
@@ -7742,6 +7785,7 @@ declare const _default: import("xstate").StateMachine<{
7742
7785
  subtitleFragments: SubtitleFragment[];
7743
7786
  subtitleStreams: SubtitleStream[];
7744
7787
  selectedSubtitleStreamIndex: number | undefined;
7788
+ indexes: Index[];
7745
7789
  thumbnails: Thumbnail[];
7746
7790
  isReady: boolean;
7747
7791
  }, {
@@ -7854,6 +7898,7 @@ declare const _default: import("xstate").StateMachine<{
7854
7898
  subtitleFragments: SubtitleFragment[];
7855
7899
  subtitleStreams: SubtitleStream[];
7856
7900
  selectedSubtitleStreamIndex: number | undefined;
7901
+ indexes: Index[];
7857
7902
  thumbnails: Thumbnail[];
7858
7903
  isReady: boolean;
7859
7904
  }, {
@@ -8125,6 +8170,7 @@ declare const _default: import("xstate").StateMachine<{
8125
8170
  subtitleFragments: SubtitleFragment[];
8126
8171
  subtitleStreams: SubtitleStream[];
8127
8172
  selectedSubtitleStreamIndex: number | undefined;
8173
+ indexes: Index[];
8128
8174
  thumbnails: Thumbnail[];
8129
8175
  isReady: boolean;
8130
8176
  }, {
@@ -8237,6 +8283,7 @@ declare const _default: import("xstate").StateMachine<{
8237
8283
  subtitleFragments: SubtitleFragment[];
8238
8284
  subtitleStreams: SubtitleStream[];
8239
8285
  selectedSubtitleStreamIndex: number | undefined;
8286
+ indexes: Index[];
8240
8287
  thumbnails: Thumbnail[];
8241
8288
  isReady: boolean;
8242
8289
  }, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@banou/media-player",
3
- "version": "0.4.6",
3
+ "version": "0.5.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "build/index.js",
@@ -1,5 +1,5 @@
1
1
  /// <reference types="@emotion/react/types/css-prop" />
2
- import { MouseEventHandler, useContext, useRef, type HTMLAttributes } from 'react'
2
+ import { MouseEventHandler, ReactNode, useContext, useRef, type HTMLAttributes } from 'react'
3
3
 
4
4
  import { css } from '@emotion/react'
5
5
 
@@ -15,6 +15,8 @@ const style = css`
15
15
  display: flex;
16
16
  justify-content: center;
17
17
  align-items: center;
18
+ height: 100%;
19
+ width: 100%;
18
20
 
19
21
  & > div:not(:last-of-type) {
20
22
  position: absolute;
@@ -33,6 +35,7 @@ const style = css`
33
35
  height: 100%;
34
36
  width: 100%;
35
37
  background-color: black;
38
+ object-fit: contain;
36
39
  }
37
40
 
38
41
  &.hide {
@@ -40,9 +43,12 @@ const style = css`
40
43
  }
41
44
  `
42
45
 
43
- export type ChromeOptions = {} & HTMLAttributes<HTMLDivElement>
46
+ export type ChromeOptions = {
47
+ mediaInformation?: ReactNode
48
+ loadingInformation?: ReactNode
49
+ } & HTMLAttributes<HTMLDivElement>
44
50
 
45
- export const Chrome = ({ children }: ChromeOptions) => {
51
+ export const Chrome = ({ children, mediaInformation, loadingInformation }: ChromeOptions) => {
46
52
  const mediaActor = MediaMachineContext.useActorRef()
47
53
  const mediaPlayerContext = useContext(MediaPlayerContext)
48
54
  const isPaused = MediaMachineContext.useSelector((state) => state.context.media.paused)
@@ -74,8 +80,8 @@ export const Chrome = ({ children }: ChromeOptions) => {
74
80
  onMouseOut={mouseOut}
75
81
  className={mediaPlayerContext.hideUI ? 'hide' : ''}
76
82
  >
77
- <Overlay />
78
- <ControlBar containerRef={containerRef} />
83
+ <Overlay loadingInformation={loadingInformation}/>
84
+ <ControlBar mediaInformation={mediaInformation} containerRef={containerRef}/>
79
85
  <div
80
86
  className='video'
81
87
  onClick={() => togglePlay(mediaActor, isPaused, duration, currentTime)}
@@ -1,4 +1,4 @@
1
- import { RefObject, useCallback, useContext, useEffect, useState } from 'react'
1
+ import { ReactNode, RefObject, useCallback, useContext, useEffect, useState } from 'react'
2
2
  import { css } from '@emotion/react'
3
3
  import { Maximize, Minimize, Pause, Play, RotateCcw } from 'react-feather'
4
4
 
@@ -129,11 +129,7 @@ const style = css`
129
129
  }
130
130
  `
131
131
 
132
- export const ControlBar = ({
133
- containerRef
134
- }: {
135
- containerRef: RefObject<HTMLDivElement>
136
- }) => {
132
+ export const ControlBar = ({ mediaInformation, containerRef }: { mediaInformation?: ReactNode, containerRef: RefObject<HTMLDivElement> }) => {
137
133
  const mediaActor = MediaMachineContext.useActorRef()
138
134
  const chromeContext = useContext(MediaPlayerContext)
139
135
  const isPaused = MediaMachineContext.useSelector((state) => state.context.media.paused)
@@ -278,6 +274,7 @@ export const ControlBar = ({
278
274
  </div>
279
275
  </div>
280
276
  <div className='right'>
277
+ {mediaInformation}
281
278
  <SettingsAction />
282
279
  <TooltipDisplay
283
280
  id='picture-in-picture'
@@ -1,9 +1,10 @@
1
1
  /// <reference types="@emotion/react/types/css-prop" />
2
2
 
3
- import { ClassAttributes, useCallback, useEffect, useState } from 'react'
3
+ import { ClassAttributes, ReactNode, useCallback, useContext, useEffect, useState } from 'react'
4
4
  import { css } from '@emotion/react'
5
5
 
6
6
  import { MediaMachineContext } from '../state-machines'
7
+ import { MediaPlayerContext } from '../utils/context'
7
8
 
8
9
  const style = css`
9
10
  top: unset !important;
@@ -11,10 +12,44 @@ const style = css`
11
12
  width: 100%;
12
13
  height: 100%;
13
14
  margin: auto;
15
+ pointer-events: none;
14
16
  `
15
17
 
16
- export const Overlay = () => {
18
+ const titleStyle = css`
19
+ position: absolute;
20
+ top: 0;
21
+ left: 0;
22
+ width: 100%;
23
+ height: 100%;
24
+ margin-left: 2.5rem;
25
+ margin-top: 2.5rem;
26
+ font-size: 2rem;
27
+ color: white;
28
+ text-shadow: 0 0 4px rgba(0, 0, 0, 1);
29
+ z-index: 2;
30
+ pointer-events: none;
31
+ `
32
+
33
+ const loadingInformationStyle = css`
34
+ position: absolute;
35
+ top: 0;
36
+ left: 0;
37
+ width: 100%;
38
+ height: 100%;
39
+ font-size: 2rem;
40
+ color: white;
41
+ text-shadow: 0 0 4px rgba(0, 0, 0, 1);
42
+ z-index: 2;
43
+ display: flex;
44
+ justify-content: center;
45
+ align-items: center;
46
+ pointer-events: none;
47
+ `
48
+
49
+ export const Overlay = ({ loadingInformation }: { loadingInformation?: ReactNode }) => {
17
50
  const mediaActor = MediaMachineContext.useActorRef()
51
+ const duration = MediaMachineContext.useSelector((state) => state.context.media.duration)
52
+ const mediaPlayerContext = useContext(MediaPlayerContext)
18
53
 
19
54
  const [canvasElement, setCanvasElement] = useState<HTMLCanvasElement | null>()
20
55
  const refFunction: ClassAttributes<HTMLCanvasElement>['ref'] = useCallback((element: HTMLCanvasElement | null) => {
@@ -31,6 +66,16 @@ export const Overlay = () => {
31
66
 
32
67
  return (
33
68
  <>
69
+ {
70
+ mediaPlayerContext.title && !mediaPlayerContext.hideUI
71
+ ? <div css={titleStyle}>{mediaPlayerContext.title}</div>
72
+ : undefined
73
+ }
74
+ {
75
+ duration === undefined && loadingInformation
76
+ ? <div css={loadingInformationStyle}>{loadingInformation}</div>
77
+ : undefined
78
+ }
34
79
  <canvas ref={refFunction} css={style}/>
35
80
  </>
36
81
  )
@@ -123,6 +123,7 @@ export const ProgressBar = () => {
123
123
  const mediaActor = MediaMachineContext.useActorRef()
124
124
  const currentTime = MediaMachineContext.useSelector((state) => state.context.media.currentTime)
125
125
  const duration = MediaMachineContext.useSelector((state) => state.context.media.duration)
126
+ const indexes = MediaMachineContext.useSelector((state) => state.context.indexes)
126
127
  const thumbnails = MediaMachineContext.useSelector((state) => state.context.thumbnails)
127
128
 
128
129
  const mediaPlayerContext = useContext(MediaPlayerContext)
@@ -148,20 +149,21 @@ export const ProgressBar = () => {
148
149
  mediaPlayerContext
149
150
  .downloadedRanges
150
151
  ?.map((range, i) => {
151
- if ('startByteOffset' in range && 'endByteOffset' in range && mediaPlayerContext.size) {
152
- const start = range.startByteOffset / mediaPlayerContext.size
153
- const end = range.endByteOffset / mediaPlayerContext.size
154
- const duration = end - start
155
- const left = start * 100
156
- return (
157
- <div key={i} className="loaded-part" style={{ transform: `scaleX(${duration})`, marginLeft: `${left}%` }}></div>
158
- )
159
- } else {
160
- return null
161
- }
152
+ if (!mediaPlayerContext.size || !duration) return null
153
+ const matchingIndexes = indexes.filter(index => range.startByteOffset <= index.pos && index.pos <= range.endByteOffset)
154
+ const firstIndex = matchingIndexes.at(0)
155
+ const lastIndex = matchingIndexes.at(-1)
156
+ if (!firstIndex || !lastIndex) return null
157
+ const start = firstIndex.timestamp / duration
158
+ const end = lastIndex.timestamp / duration
159
+ const rangeDuration = Number((end - start).toFixed(2)) // to prevent cases like `0.9995140832939585`
160
+ const left = start * 100
161
+ return (
162
+ <div key={i} className="loaded-part" style={{ transform: `scaleX(${rangeDuration})`, marginLeft: `${left}%` }}></div>
163
+ )
162
164
  })
163
165
  ?? [],
164
- [mediaPlayerContext.downloadedRanges?.map(({ startByteOffset, endByteOffset }) => `${startByteOffset}/${endByteOffset}`).join(',')]
166
+ [duration, indexes.length, mediaPlayerContext.downloadedRanges?.map(({ startByteOffset, endByteOffset }) => `${startByteOffset}/${endByteOffset}`).join(',')]
165
167
  )
166
168
 
167
169
  const cusorTimeString = useMemo(() => {
package/src/index.tsx CHANGED
@@ -17,6 +17,7 @@ const FKNVideoRootStyle = css`
17
17
  justify-content: center;
18
18
  background-color: #111;
19
19
  height: 100%;
20
+ width: 100%;
20
21
  overflow: hidden;
21
22
  `
22
23
 
@@ -26,6 +27,9 @@ export type FKNVideoOptions = {
26
27
  read?: (offset: number, size: number) => Promise<ArrayBuffer>
27
28
  size?: number
28
29
  bufferSize?: number
30
+ autoplay?: boolean
31
+ mediaInformation?: ReactNode
32
+ loadingInformation?: ReactNode
29
33
  publicPath: string
30
34
  jassubWorkerUrl: string
31
35
  jassubWasmUrl: string
@@ -43,17 +47,22 @@ export const FKNVideoRoot = (
43
47
  const volume = MediaMachineContext.useSelector((state) => state.context.media.volume)
44
48
  const muted = MediaMachineContext.useSelector((state) => state.context.media.muted)
45
49
  const isReady = MediaMachineContext.useSelector((state) => state.context.isReady)
50
+ const duration = MediaMachineContext.useSelector((state) => state.context.media.duration)
46
51
  const [mediaVolume, setMediaVolume] = useLocalStorage('mediaVolume', '1') as [string, (newValue: string) => void]
47
52
  const [mediaMute, setMediaMute] = useLocalStorage('mediaMute', 'false') as [mediaMutedType, (newValue: mediaMutedType) => void]
48
53
  const [firstRender, setFirstRender] = useState(true)
49
54
 
50
- useEffect(
51
- () => mediaActor.send({
55
+ useEffect(() => {
56
+ mediaActor.send({
52
57
  type: 'MEDIA_SOURCE_OPTIONS',
53
58
  mediaSourceOptions: {}
54
- }),
55
- []
56
- )
59
+ })
60
+ }, [])
61
+
62
+ useEffect(() => {
63
+ if (!options.autoplay || duration === undefined) return
64
+ mediaActor.send({ type: 'PLAY' })
65
+ }, [duration, options.autoplay])
57
66
 
58
67
  useEffect(
59
68
  () => {
@@ -140,7 +149,7 @@ export const FKNVideoRoot = (
140
149
 
141
150
  return (
142
151
  <div css={FKNVideoRootStyle}>
143
- <Chrome>
152
+ <Chrome mediaInformation={options.mediaInformation} loadingInformation={options.loadingInformation}>
144
153
  {children}
145
154
  </Chrome>
146
155
  </div>
package/src/main.tsx CHANGED
@@ -91,6 +91,7 @@ const Mount = () => {
91
91
  bufferSize={BASE_BUFFER_SIZE}
92
92
  read={read}
93
93
  size={contentLength}
94
+ autoplay={true}
94
95
  publicPath={new URL('/build/', new URL(import.meta.url).origin).toString()}
95
96
  jassubModernWasmUrl={jassubModernWasmUrl}
96
97
  jassubWorkerUrl={jassubWorkerUrl}
@@ -31,6 +31,7 @@ export default fromAsyncCallback<DataSourceEvents, DataSourceInput, DataSourceEm
31
31
  })
32
32
 
33
33
  const metadata = await remuxer.init()
34
+ if (metadata.indexes) sendBack({ type: 'INDEXES', indexes: metadata.indexes })
34
35
  if (metadata.attachments?.length) sendBack({ type: 'NEW_ATTACHMENTS', attachments: metadata.attachments })
35
36
  if (metadata.subtitles?.length) sendBack({ type: 'NEW_SUBTITLE_FRAGMENTS', subtitles: metadata.subtitles })
36
37
  sendBack({ type: 'METADATA', ...metadata })
@@ -1,4 +1,4 @@
1
- import type { Attachment, SubtitleFragment } from 'libav-wasm/build/worker'
1
+ import type { Attachment, Index, SubtitleFragment } from 'libav-wasm/build/worker'
2
2
 
3
3
  import { makeRemuxer } from 'libav-wasm'
4
4
  import { assign, setup, sendTo, enqueueActions } from 'xstate'
@@ -31,6 +31,7 @@ export default setup({
31
31
  subtitleFragments: SubtitleFragment[]
32
32
  subtitleStreams: SubtitleStream[]
33
33
  selectedSubtitleStreamIndex: number | undefined
34
+ indexes: Index[]
34
35
  thumbnails: Thumbnail[]
35
36
  isReady: boolean
36
37
  },
@@ -99,6 +100,7 @@ export default setup({
99
100
  subtitleFragments: [],
100
101
  subtitleStreams: [],
101
102
  selectedSubtitleStreamIndex: undefined,
103
+ indexes: [],
102
104
  thumbnails: [],
103
105
  isReady: false
104
106
  },
@@ -208,6 +210,11 @@ export default setup({
208
210
  'TIMESTAMP_OFFSET': { actions: sendTo('mediaSource', ({ event }) => event) },
209
211
  'NEW_THUMBNAIL': { actions: [assign({ thumbnails: ({ context, event }) => [...context.thumbnails, event.thumbnail] })] },
210
212
  'DOWNLOADED_RANGES_UPDATED': { actions: sendTo('thumbnails', ({ event }) => event) },
213
+ 'INDEXES': {
214
+ actions: [
215
+ assign({ indexes: ({ event }) => event.indexes })
216
+ ]
217
+ },
211
218
  'NEW_ATTACHMENTS': {
212
219
  actions: [
213
220
  assign({ attachments: ({ context, event }) => [...context.attachments, ...event.attachments] }),