Skip to content

Commit 9b4971f

Browse files
authored
Merge pull request #289 from boostcampwm-2024/feature-FE-##287-1-Host_use_SessionKey
[FIX] 플레이어 리트라이 및 시간 정리
2 parents fb98ecc + 8575471 commit 9b4971f

File tree

1 file changed

+68
-61
lines changed

1 file changed

+68
-61
lines changed

frontend/src/hooks/usePlayer.ts

Lines changed: 68 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,72 @@
1-
import Hls, {
2-
Loader,
3-
LoaderCallbacks,
4-
LoaderConfiguration,
5-
LoaderContext,
6-
LoaderResponse,
7-
LoaderStats,
8-
HlsConfig
9-
} from 'hls.js';
1+
import Hls, { Loader, LoaderCallbacks, LoaderConfiguration, LoaderContext, HlsConfig } from 'hls.js';
102
import { useEffect, useRef } from 'react';
113

124
class CustomLoader implements Loader<LoaderContext> {
135
private loader: Loader<LoaderContext>;
6+
private retryCount: number = 0;
7+
private maxRetries: number = 6;
8+
private retryDelay: number = 3000;
9+
private DefaultLoader: new (config: HlsConfig) => Loader<LoaderContext>;
1410

1511
constructor(config: HlsConfig) {
16-
const DefaultLoader = Hls.DefaultConfig.loader as new (config: HlsConfig) => Loader<LoaderContext>;
17-
this.loader = new DefaultLoader(config);
12+
this.DefaultLoader = Hls.DefaultConfig.loader as new (config: HlsConfig) => Loader<LoaderContext>;
13+
this.loader = new this.DefaultLoader(config);
1814
}
1915

20-
load(context: LoaderContext, config: LoaderConfiguration, callbacks: LoaderCallbacks<LoaderContext>) {
21-
const { onSuccess, onError, onTimeout, onAbort, onProgress } = callbacks;
16+
private createNewLoader(): Loader<LoaderContext> {
17+
return new this.DefaultLoader({
18+
...Hls.DefaultConfig,
19+
enableWorker: true,
20+
lowLatencyMode: true
21+
});
22+
}
2223

23-
const newCallbacks: LoaderCallbacks<LoaderContext> = {
24-
onSuccess: (response: LoaderResponse, stats: LoaderStats, context: LoaderContext, networkDetails: any = null) => {
25-
onSuccess(response, stats, context, networkDetails);
26-
},
27-
onError: (
28-
error: { code: number; text: string },
29-
context: LoaderContext,
30-
networkDetails: any = null,
31-
stats: LoaderStats
32-
) => {
33-
if (error.code === 404) {
34-
const emptyData = new ArrayBuffer(0);
35-
onSuccess(
36-
{
37-
url: context.url,
38-
data: emptyData
39-
},
40-
{
41-
trequest: performance.now(),
42-
tfirst: performance.now(),
43-
tload: performance.now(),
44-
loaded: 0,
45-
total: 0
46-
} as unknown as LoaderStats,
47-
context,
48-
networkDetails
49-
);
50-
} else {
51-
if (onError) {
52-
onError(error, context, networkDetails, stats);
24+
private retryLoad(context: LoaderContext, config: LoaderConfiguration, callbacks: LoaderCallbacks<LoaderContext>) {
25+
this.loader = this.createNewLoader();
26+
27+
setTimeout(() => {
28+
const retryCallbacks: LoaderCallbacks<LoaderContext> = {
29+
...callbacks,
30+
onError: (error, context, networkDetails, stats) => {
31+
if (error.code === 404 && this.retryCount < this.maxRetries) {
32+
this.retryCount++;
33+
this.retryLoad(context, config, callbacks);
34+
} else {
35+
this.retryCount = 0;
36+
if (callbacks.onError) {
37+
callbacks.onError(error, context, networkDetails, stats);
38+
}
5339
}
5440
}
55-
},
56-
onTimeout: (stats: LoaderStats, context: LoaderContext, networkDetails: any = null) => {
57-
if (onTimeout) {
58-
onTimeout(stats, context, networkDetails);
59-
}
60-
},
61-
onAbort: (stats: LoaderStats, context: LoaderContext, networkDetails: any = null) => {
62-
if (onAbort) {
63-
onAbort(stats, context, networkDetails);
41+
};
42+
43+
this.loader.load(context, config, retryCallbacks);
44+
}, this.retryDelay);
45+
}
46+
47+
load(context: LoaderContext, config: LoaderConfiguration, callbacks: LoaderCallbacks<LoaderContext>) {
48+
const modifiedCallbacks: LoaderCallbacks<LoaderContext> = {
49+
...callbacks,
50+
onSuccess: (response, stats, context, networkDetails) => {
51+
this.retryCount = 0;
52+
if (callbacks.onSuccess) {
53+
callbacks.onSuccess(response, stats, context, networkDetails);
6454
}
6555
},
66-
onProgress: (
67-
stats: LoaderStats,
68-
context: LoaderContext,
69-
data: string | ArrayBuffer,
70-
networkDetails: any = null
71-
) => {
72-
if (onProgress) {
73-
onProgress(stats, context, data, networkDetails);
56+
onError: (error, context, networkDetails, stats) => {
57+
if (error.code === 404 && this.retryCount < this.maxRetries) {
58+
this.retryCount++;
59+
this.retryLoad(context, config, callbacks);
60+
} else {
61+
this.retryCount = 0;
62+
if (callbacks.onError) {
63+
callbacks.onError(error, context, networkDetails, stats);
64+
}
7465
}
7566
}
7667
};
7768

78-
this.loader.load(context, config, newCallbacks);
69+
this.loader.load(context, config, modifiedCallbacks);
7970
}
8071

8172
abort() {
@@ -124,6 +115,22 @@ export default function usePlayer(url: string) {
124115
videoElement.play();
125116
});
126117

118+
hls.on(Hls.Events.ERROR, (event, data) => {
119+
if (data.fatal) {
120+
switch (data.type) {
121+
case Hls.ErrorTypes.NETWORK_ERROR:
122+
hls.startLoad();
123+
break;
124+
case Hls.ErrorTypes.MEDIA_ERROR:
125+
hls.recoverMediaError();
126+
break;
127+
default:
128+
hls.destroy();
129+
break;
130+
}
131+
}
132+
});
133+
127134
return () => {
128135
hls.destroy();
129136
};

0 commit comments

Comments
 (0)