Skip to content

Commit 1a322c3

Browse files
committed
Improve stability
1 parent 4e93168 commit 1a322c3

File tree

3 files changed

+69
-5
lines changed

3 files changed

+69
-5
lines changed

apps/web/organisms/live/live-app.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export const LiveApp: FC<Props> = ({ live, streamer }) => {
103103
liveTitle={live.title}
104104
userId={user?.id}
105105
comments={comments}
106+
key={url?.flvWs} // 強制再読み込み用
106107
/>
107108
) : (
108109
<VideoMessageBox

apps/web/organisms/live/video/live-player.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ type Props = {
2424
comments: CommentPublic[];
2525
};
2626

27+
// コンポーネント再マウントしても保持したいのでとりあえず
28+
let stealingCount = 0;
29+
2730
export const LivePlayer: FC<Props> = ({
2831
thumbnailUrl,
2932
url,
@@ -48,7 +51,11 @@ export const LivePlayer: FC<Props> = ({
4851
const [canPlay, setCanPlay] = useState(false);
4952
const [maybeBlocked, setMaybeBlocked] = useState(false);
5053
const [danmaku, setDanmaku] = useState(true);
51-
const { playType, setPlayType, play } = useVideoStream('live', videoRef, url);
54+
const { playType, setPlayType, play, handleToLowerQuality } = useVideoStream(
55+
'live',
56+
videoRef,
57+
url
58+
);
5259
useMuxData(videoRef, liveId, liveTitle, userId, playType);
5360

5461
const autoSeek = useCallback(() => {
@@ -217,6 +224,29 @@ export const LivePlayer: FC<Props> = ({
217224
}
218225
}, [comments, danmaku]);
219226

227+
useEffect(() => {
228+
if (latency > 0 || !canPlay) {
229+
return;
230+
}
231+
232+
const timeout = setTimeout(() => {
233+
// 長期間バッファチェック
234+
235+
stealingCount++;
236+
console.warn('Stealing, count:', stealingCount);
237+
// 連続でバッファリングが発生した場合は画質を下げる
238+
if (stealingCount > 2) {
239+
stealingCount = 0;
240+
handleToLowerQuality();
241+
console.warn('Stealing, lower quality');
242+
}
243+
244+
void updateUrl();
245+
}, 5 * 1000);
246+
247+
return () => clearTimeout(timeout);
248+
}, [latency, handleToLowerQuality, canPlay, updateUrl]);
249+
220250
return (
221251
<Box
222252
{...events}

apps/web/utils/hooks/use-video-stream.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import { LiveUrls } from 'api-types/api/v1/lives/_liveId@number/url';
55
import { useAPIError } from './api/use-api-error';
66
import { VideoUrls } from 'api-types/api/v1/videos/_liveId@number';
77
import type { HlsConfig } from 'hls.js';
8+
import { useLocalStorage } from 'react-use';
89

910
export enum LivePlayType {
10-
FlvHttp = 'flvHttp',
1111
FlvWs = 'flvWs',
12+
FlvHttp = 'flvHttp',
1213
HlsHq = 'hlsHq',
1314
HlsLq = 'hlsLq',
1415
Audio = 'audio'
@@ -31,14 +32,19 @@ type UrlType<T> = T extends 'live' ? LiveUrls : VideoUrls;
3132
let hlsInterface: typeof Hls | undefined;
3233
let mpegtsInterface: typeof Mpegts | undefined;
3334

35+
const isLivePlayType = (type: string): type is LivePlayType =>
36+
Object.values(LivePlayType).includes(type as LivePlayType);
37+
3438
export const useVideoStream = <T extends 'live' | 'video'>(
3539
entityType: T,
3640
videoTagRef: RefObject<HTMLVideoElement>,
3741
url?: UrlType<T>
3842
) => {
3943
const mpegtsPlayerRef = useRef<Mpegts.Player>();
4044
const hlsPlayerRef = useRef<Hls>();
41-
const [playType, setPlayType] = useState<PlayType<T>>();
45+
const [playType, setPlayType] = useLocalStorage<PlayType<T>>(
46+
`knzklive-${entityType}-play-type`
47+
);
4248
const [error, setError] = useState<unknown>();
4349
useAPIError(error);
4450

@@ -210,6 +216,24 @@ export const useVideoStream = <T extends 'live' | 'video'>(
210216
[videoTagRef]
211217
);
212218

219+
const handleToLowerQuality = useCallback(() => {
220+
if (!playType) {
221+
return;
222+
}
223+
if (isLivePlayType(playType)) {
224+
const qualities = Object.values(LivePlayType);
225+
const currentIndex = qualities.indexOf(playType);
226+
const nextQuality = qualities[currentIndex + 1];
227+
if (nextQuality && nextQuality !== LivePlayType.Audio) {
228+
setPlayType(nextQuality as PlayType<T>);
229+
230+
return true;
231+
}
232+
}
233+
234+
return false;
235+
}, [playType, setPlayType]);
236+
213237
useEffect(() => {
214238
const video = videoTagRef.current;
215239
if (!video || !url) {
@@ -273,12 +297,21 @@ export const useVideoStream = <T extends 'live' | 'video'>(
273297
video.src = '';
274298
}
275299
};
276-
}, [videoTagRef, url, playType, handleFlv, handleHls, entityType]);
300+
}, [
301+
videoTagRef,
302+
url,
303+
playType,
304+
handleFlv,
305+
handleHls,
306+
entityType,
307+
setPlayType
308+
]);
277309

278310
return {
279311
playType,
280312
setPlayType,
281-
play
313+
play,
314+
handleToLowerQuality
282315
} as const;
283316
};
284317

0 commit comments

Comments
 (0)