From 97ac10c675c6ccd4df407fe7f8e5dd0b1798d973 Mon Sep 17 00:00:00 2001 From: optrader Date: Mon, 24 Nov 2025 17:26:28 +0900 Subject: [PATCH] =?UTF-8?q?[251124]=20fix:=20PlayerPanel,VideoPlayer=20?= =?UTF-8?q?=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🕐 커밋 시간: 2025. 11. 24. 17:26:27 📊 변경 통계: • 총 파일: 2개 • 추가: +22줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/reducers/playReducer.js ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx 🔧 주요 변경 내용: • 핵심 비즈니스 로직 개선 • 소규모 기능 개선 --- .../src/reducers/playReducer.js | 1 + .../src/views/PlayerPanel/PlayerPanel.jsx | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/com.twin.app.shoptime/src/reducers/playReducer.js b/com.twin.app.shoptime/src/reducers/playReducer.js index dbe0a67c..a94fc7f3 100644 --- a/com.twin.app.shoptime/src/reducers/playReducer.js +++ b/com.twin.app.shoptime/src/reducers/playReducer.js @@ -93,6 +93,7 @@ export const playReducer = (state = initialState, action) => { return { ...state, chatData: {}, + subTitleBlobs: {}, }; } case types.UPDATE_VIDEO_PLAY_STATE: { diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx index 408c818e..c44e9fea 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx @@ -260,6 +260,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props const showNowInfos = USE_SELECTOR('showNowInfos', (state) => state.main.showNowInfo); const liveShowInfos = USE_SELECTOR('liveShowInfos', (state) => state.main.liveShowInfos); const vodSubtitleData = USE_SELECTOR('vodSubtitleData', (state) => state.play.subTitleBlobs); + const previousSubtitleBlobRef = useRef(null); const broadcast = USE_SELECTOR('broadcast', (state) => state.common.broadcast); const videoPlayState = USE_SELECTOR('videoPlayState', (state) => state.play.videoPlayState); @@ -1892,6 +1893,26 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props return vodSubtitleData[currentSubtitleUrl]; }, [vodSubtitleData, currentSubtitleUrl]); + // 자막 Blob URL 수명 관리: 이전 Blob을 해제해 메모리 누수 방지 + useEffect(() => { + const prevBlobUrl = previousSubtitleBlobRef.current; + if (prevBlobUrl && prevBlobUrl !== currentSubtitleBlob && typeof prevBlobUrl === 'string') { + if (prevBlobUrl.startsWith('blob:')) { + URL.revokeObjectURL(prevBlobUrl); + } + } + + previousSubtitleBlobRef.current = currentSubtitleBlob; + + return () => { + const lastBlobUrl = previousSubtitleBlobRef.current; + if (lastBlobUrl && typeof lastBlobUrl === 'string' && lastBlobUrl.startsWith('blob:')) { + URL.revokeObjectURL(lastBlobUrl); + } + previousSubtitleBlobRef.current = null; + }; + }, [currentSubtitleBlob]); + const isReadyToPlay = useMemo(() => { if (!currentPlayingUrl) { return false;