@banou/media-player 0.3.0 → 0.4.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.
Files changed (74) hide show
  1. package/README.md +0 -10
  2. package/build/components/chrome.d.ts +4 -0
  3. package/build/components/control-bar.d.ts +5 -0
  4. package/build/components/overlay.d.ts +1 -0
  5. package/build/components/progress-bar.d.ts +1 -0
  6. package/build/components/settings.d.ts +2 -0
  7. package/build/components/sound.d.ts +4 -0
  8. package/build/components/tooltip-display.d.ts +20 -0
  9. package/build/components/volume-slider.d.ts +6 -0
  10. package/build/index.d.ts +23 -48
  11. package/build/index.js +2576 -2250
  12. package/build/main.d.ts +1 -1
  13. package/build/state-machines/data-source.d.ts +27 -0
  14. package/build/state-machines/index.d.ts +33185 -0
  15. package/build/state-machines/media-properties.d.ts +45 -0
  16. package/build/state-machines/media-source.d.ts +34 -0
  17. package/build/state-machines/media.d.ts +8344 -0
  18. package/build/state-machines/subtitles.d.ts +53 -0
  19. package/build/state-machines/thumbnails.d.ts +24 -0
  20. package/build/state-machines/utils.d.ts +26 -0
  21. package/build/utils/actor-utils.d.ts +2 -0
  22. package/build/utils/colors.d.ts +8 -0
  23. package/build/utils/context.d.ts +14 -0
  24. package/build/utils/fonts.d.ts +28 -0
  25. package/build/{utils.d.ts → utils/index.d.ts} +4 -12
  26. package/build/utils/languages.d.ts +260 -0
  27. package/build/{mp4box.d.ts → utils/mp4box.d.ts} +61 -61
  28. package/build/utils/time.d.ts +2 -0
  29. package/build/utils/use-local-storage.d.ts +3 -0
  30. package/build/{use-scrub.d.ts → utils/use-scrub.d.ts} +11 -11
  31. package/build/utils/volume-utils.d.ts +17 -0
  32. package/build/utils/window-height.d.ts +2 -0
  33. package/package.json +15 -12
  34. package/src/assets/picture-in-picture.svg +5 -0
  35. package/src/components/chrome.tsx +89 -0
  36. package/src/components/control-bar.tsx +330 -0
  37. package/src/components/overlay.tsx +28 -0
  38. package/src/components/progress-bar.tsx +252 -0
  39. package/src/components/settings.tsx +269 -0
  40. package/src/components/sound.tsx +101 -0
  41. package/src/components/tooltip-display.tsx +83 -0
  42. package/src/components/volume-slider.tsx +156 -0
  43. package/src/index.tsx +145 -435
  44. package/src/main.tsx +66 -39
  45. package/src/state-machines/data-source.ts +83 -0
  46. package/src/state-machines/index.ts +5 -0
  47. package/src/state-machines/media-properties.ts +78 -0
  48. package/src/state-machines/media-source.ts +129 -0
  49. package/src/state-machines/media.ts +245 -0
  50. package/src/state-machines/subtitles.ts +247 -0
  51. package/src/state-machines/thumbnails.ts +123 -0
  52. package/src/state-machines/utils.ts +94 -0
  53. package/src/utils/actor-utils.ts +19 -0
  54. package/src/utils/colors.ts +9 -0
  55. package/src/utils/context.ts +23 -0
  56. package/src/utils/fonts.ts +156 -0
  57. package/src/{utils.ts → utils/index.ts} +2 -26
  58. package/src/utils/time.ts +16 -0
  59. package/src/utils/use-local-storage.ts +30 -0
  60. package/src/utils/volume-utils.ts +39 -0
  61. package/src/utils/window-height.ts +19 -0
  62. package/tsconfig.json +4 -2
  63. package/build/chrome/bottom.d.ts +0 -22
  64. package/build/chrome/index.d.ts +0 -28
  65. package/build/chrome/overlay.d.ts +0 -9
  66. package/build/languages.d.ts +0 -260
  67. package/build/use-local-storage.d.ts +0 -6
  68. package/src/chrome/bottom.tsx +0 -697
  69. package/src/chrome/index.tsx +0 -203
  70. package/src/chrome/overlay.tsx +0 -104
  71. package/src/use-local-storage.ts +0 -32
  72. /package/src/{languages.ts → utils/languages.ts} +0 -0
  73. /package/src/{mp4box.ts → utils/mp4box.ts} +0 -0
  74. /package/src/{use-scrub.ts → utils/use-scrub.ts} +0 -0
@@ -1,203 +0,0 @@
1
- /// <reference types="@emotion/react/types/css-prop" />
2
- import type { ClassAttributes, HTMLAttributes, MouseEventHandler, MutableRefObject, ReactNode } from 'react'
3
- import type { Attachment, FKNVideoControl, Subtitle, TransmuxError } from '..'
4
-
5
- import { useEffect, useMemo, useRef, useState } from 'react'
6
- import JASSUB from 'jassub'
7
- import { css } from '@emotion/react'
8
- import Overlay from './overlay'
9
- import Bottom from './bottom'
10
-
11
- const style = css`
12
- --background-padding: 2rem;
13
- display: grid;
14
- grid-template-rows: 1fr;
15
- overflow: hidden;
16
-
17
- &.hide {
18
- cursor: none;
19
-
20
- .bottom {
21
- opacity: 0;
22
- }
23
- }
24
-
25
- .bottom {
26
- &.hide {
27
- opacity: 0 !important;
28
- }
29
- }
30
- `
31
-
32
- export type ChromeOptions = {
33
- publicPath: string
34
- customOverlay?: ReactNode
35
- isPlaying?: boolean
36
- loading?: boolean
37
- duration?: number
38
- loadedTime?: [number, number]
39
- currentTime?: number
40
- pictureInPicture: () => void
41
- fullscreen: () => void
42
- play: () => void
43
- seek: (time: number) => void
44
- getVolume: () => number | undefined
45
- setVolume: (volume: number) => void
46
- attachments: Attachment[] | undefined
47
- tracks: Subtitle[]
48
- video: MutableRefObject<HTMLVideoElement | undefined>
49
- videoReactive: HTMLVideoElement | undefined,
50
- errors: TransmuxError[]
51
- customControls?: FKNVideoControl[]
52
- libassWorkerUrl: string
53
- wasmUrl: string
54
- needsInitialInteraction?: boolean
55
- } & HTMLAttributes<HTMLDivElement>
56
-
57
- export default ({
58
- customOverlay,
59
- publicPath,
60
- isPlaying,
61
- loading,
62
- duration,
63
- loadedTime,
64
- currentTime,
65
- pictureInPicture,
66
- fullscreen,
67
- play,
68
- seek,
69
- getVolume,
70
- setVolume,
71
- attachments,
72
- tracks,
73
- video,
74
- videoReactive,
75
- errors,
76
- customControls,
77
- libassWorkerUrl,
78
- wasmUrl,
79
- needsInitialInteraction,
80
- ...rest
81
- }: ChromeOptions) => {
82
- const [canvasElement, setCanvasElement] = useState<HTMLCanvasElement | undefined>()
83
- const [canvasInitialized, setCanvasInitialized] = useState(false)
84
- const [isFullscreen, setFullscreen] = useState(false)
85
- const [hidden, setHidden] = useState(false)
86
- const autoHide = useRef<number>()
87
- const [isSubtitleMenuHidden, setIsSubtitleMenuHidden] = useState(true)
88
- const [jassub, setJassub] = useState<JASSUB>()
89
- const [currentSubtitleTrack, setCurrentSubtitleTrack] = useState<number | undefined>()
90
- const subtitleTrack = useMemo(
91
- () => currentSubtitleTrack !== undefined ? tracks[currentSubtitleTrack] : undefined,
92
- [currentSubtitleTrack, currentSubtitleTrack !== undefined && tracks[currentSubtitleTrack]?.data]
93
- )
94
- const [isErrorMenuHidden, setIsErrorMenuHidden] = useState(true)
95
-
96
- const mouseMove: MouseEventHandler<HTMLDivElement> = (ev) => {
97
- setHidden(false)
98
- if (autoHide.current) clearInterval(autoHide.current)
99
- const timeout = setTimeout(() => {
100
- setHidden(true)
101
- }, 3_000) as unknown as number
102
- autoHide.current = timeout
103
- }
104
-
105
- // hide automatically after 3 seconds, in case the user doesn't move the mouse on init
106
- useEffect(() => {
107
- setTimeout(() => {
108
- setHidden(true)
109
- }, 3_000)
110
- }, [])
111
-
112
- const mouseOut: React.DOMAttributes<HTMLDivElement>['onMouseOut'] = (ev) => {
113
- const root = canvasElement?.parentElement?.parentElement
114
- if (!root?.contains(ev?.relatedTarget as Element)) {
115
- setHidden(true)
116
- return
117
- }
118
- if (ev.currentTarget.parentElement !== ev.relatedTarget && ev.relatedTarget !== null) return
119
- setHidden(true)
120
- }
121
-
122
- const togglePlay = () => {
123
- if (!isSubtitleMenuHidden) return
124
- play()
125
- }
126
-
127
- const toggleFullscreen = () => {
128
- if (!canvasElement || !jassub) return
129
- setFullscreen(value => !value)
130
- fullscreen()
131
- }
132
-
133
- useEffect(() => {
134
- if (!video.current || !canvasElement || jassub || !subtitleTrack?.data || !attachments) return
135
- const fonts = attachments.map(({ filename, data }) => [
136
- filename.toLowerCase().replaceAll('-', ' ').split('.').at(0),
137
- data
138
- ])
139
- const jassubInstance = new JASSUB({
140
- video: video.current,
141
- canvas: canvasElement,
142
- subContent: subtitleTrack.data,
143
- fonts: fonts.filter(Boolean).map(([,filename]) => filename as string),
144
- availableFonts: { ...Object.fromEntries(fonts), 'liberation sans': `${publicPath}default.woff2` },
145
- workerUrl: libassWorkerUrl, // Link to WebAssembly-based file "libassjs-worker.js",
146
- modernWasmUrl: wasmUrl
147
- })
148
- setJassub(jassubInstance)
149
- }, [canvasElement, attachments, subtitleTrack?.data])
150
-
151
- useEffect(() => {
152
- if (!tracks.length) return
153
- setCurrentSubtitleTrack(0)
154
- }, [tracks.length])
155
-
156
- useEffect(() => {
157
- if (!jassub) return
158
- if (!subtitleTrack) {
159
- jassub.freeTrack()
160
- return
161
- }
162
- jassub.setTrack(subtitleTrack.data)
163
- const parent = canvasElement?.parentElement
164
- if (!parent || canvasInitialized) return
165
- setCanvasInitialized(true)
166
- }, [jassub, subtitleTrack, canvasInitialized])
167
-
168
- const setCanvasRef: ClassAttributes<HTMLCanvasElement>['ref'] = (canvasElem) => {
169
- if (!canvasElem) return
170
- setCanvasElement(canvasElem)
171
- }
172
-
173
- return (
174
- <div {...rest} css={style} onMouseMove={mouseMove} onMouseOut={mouseOut} className={`chrome ${rest.className ?? ''} ${hidden ? 'hide' : ''}`}>
175
- <Overlay needsInitialInteraction={needsInitialInteraction} loading={loading} togglePlay={togglePlay} setCanvasRef={setCanvasRef}/>
176
- {customOverlay}
177
- <Bottom
178
- className={`bottom ${needsInitialInteraction ? 'hide' : ''}`}
179
- toggleFullscreen={toggleFullscreen}
180
- togglePlay={togglePlay}
181
- isFullscreen={isFullscreen}
182
- pictureInPicture={pictureInPicture}
183
- video={video}
184
- videoReactive={videoReactive}
185
- seek={seek}
186
- setCurrentSubtitleTrack={setCurrentSubtitleTrack}
187
- isSubtitleMenuHidden={isSubtitleMenuHidden}
188
- setIsSubtitleMenuHidden={setIsSubtitleMenuHidden}
189
- isErrorMenuHidden={isErrorMenuHidden}
190
- setIsErrorMenuHidden={setIsErrorMenuHidden}
191
- setVolume={setVolume}
192
- subtitleTrack={subtitleTrack}
193
- tracks={tracks}
194
- currentTime={currentTime}
195
- duration={duration}
196
- isPlaying={isPlaying}
197
- loadedTime={loadedTime}
198
- errors={errors}
199
- customControls={customControls}
200
- />
201
- </div>
202
- )
203
- }
@@ -1,104 +0,0 @@
1
- /// <reference types="@emotion/react/types/css-prop" />
2
- import type { ClassAttributes } from 'react'
3
-
4
- import { css } from '@emotion/react'
5
-
6
- const style = css`
7
- position: relative;
8
- display: grid;
9
- grid-column: 1;
10
- grid-row: 1;
11
- display: grid;
12
- height: 100%;
13
- width: 100%;
14
- justify-items: center;
15
- align-items: center;
16
-
17
- canvas {
18
- pointer-events: none;
19
- position: absolute;
20
- inset: 0;
21
- grid-column: 1;
22
- grid-row: 1;
23
- height: 100%;
24
- width: 100%;
25
- }
26
-
27
- .loading {
28
- grid-column: 1;
29
- grid-row: 1;
30
- }
31
- `
32
-
33
- export type OverlayOptions = {
34
- loading?: boolean
35
- togglePlay: (ev: any) => void
36
- setCanvasRef: ClassAttributes<HTMLCanvasElement>['ref'],
37
- needsInitialInteraction?: boolean
38
- }
39
-
40
- export default ({ loading, needsInitialInteraction, togglePlay, setCanvasRef }: OverlayOptions) => {
41
- return (
42
- <div css={style} onClick={togglePlay}>
43
- <canvas ref={setCanvasRef}/>
44
- {
45
- needsInitialInteraction
46
- ? (
47
- <svg
48
- xmlns="http://www.w3.org/2000/svg"
49
- width="60"
50
- height="60"
51
- viewBox="0 0 60 60"
52
- fill="black"
53
- stroke="currentColor"
54
- strokeWidth="3"
55
- strokeLinecap="round"
56
- strokeLinejoin="round"
57
- className="feather feather-play"
58
- >
59
- <polygon points="12 7 45 28 12 50 12 7"></polygon>
60
- </svg>
61
- )
62
- : (
63
- loading
64
- ? (
65
- <svg
66
- className="loading"
67
- xmlns="http://www.w3.org/2000/svg"
68
- style={{
69
- display: 'block',
70
- shapeRendering: 'auto',
71
- animationPlayState: 'running',
72
- animationDelay: '0s',
73
- }}
74
- width="100" height="100"
75
- viewBox="0 0 100 100"
76
- preserveAspectRatio="xMidYMid"
77
- >
78
- <circle
79
- cx="50"
80
- cy="50"
81
- fill="none"
82
- stroke="currentColor"
83
- strokeWidth="9"
84
- r="35"
85
- strokeDasharray="164.93361431346415 56.97787143782138"
86
- style={{ animationPlayState: 'running', animationDelay: '0s' }}>
87
- <animateTransform
88
- attributeName="transform"
89
- type="rotate"
90
- repeatCount="indefinite"
91
- dur="1s"
92
- values="0 50 50;360 50 50"
93
- keyTimes="0;1"
94
- style={{ animationPlayState: 'running', animationDelay: '0s' }}
95
- />
96
- </circle>
97
- </svg>
98
- )
99
- : null
100
- )
101
- }
102
- </div>
103
- )
104
- }
@@ -1,32 +0,0 @@
1
- import { useEffect, useState } from 'react'
2
-
3
- const useNamespacedLocalStorage = <T extends { [key: PropertyKey]: string | boolean | number | undefined | null | object | any[] }>(namespace: string) => {
4
- const [state, setState] = useState<T>(() => {
5
- const storedValue = localStorage.getItem(namespace)
6
- return (
7
- storedValue
8
- ? JSON.parse(storedValue)
9
- : {}
10
- )
11
- })
12
-
13
- useEffect(() => {
14
- localStorage.setItem(namespace, JSON.stringify(state));
15
- }, [namespace, state])
16
-
17
- return <T2 extends keyof T, T3 extends T[T2]>(key: T2, value: T[T2]) => {
18
- useEffect(() => {
19
- setState(state => ({ ...state, [key]: value }))
20
- }, [])
21
- return [
22
- state[key],
23
- (newValue: T3 | ((oldValue: T3) => T3)) =>
24
- typeof newValue === 'function'
25
- // @ts-expect-error
26
- ? setState(state => ({ ...state, [key]: newValue(state[key]) }))
27
- : setState(state => ({ ...state, [key]: newValue }))
28
- ] as const
29
- }
30
- }
31
-
32
- export default useNamespacedLocalStorage
File without changes
File without changes
File without changes