[251125] memory monitoring
This commit is contained in:
@@ -66,10 +66,12 @@ import TReactPlayer from './TReactPlayer';
|
|||||||
import Video from './Video';
|
import Video from './Video';
|
||||||
import css from './VideoPlayer.module.less';
|
import css from './VideoPlayer.module.less';
|
||||||
import { updateVideoPlayState } from '../../actions/playActions';
|
import { updateVideoPlayState } from '../../actions/playActions';
|
||||||
|
import createMemoryMonitor from '../../utils/memoryMonitor';
|
||||||
|
|
||||||
// 디버그 헬퍼 설정
|
// 디버그 헬퍼 설정
|
||||||
const DEBUG_MODE = false;
|
const DEBUG_MODE = false;
|
||||||
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
|
const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE);
|
||||||
|
const memoryMonitor = createMemoryMonitor();
|
||||||
|
|
||||||
const isEnter = is('enter');
|
const isEnter = is('enter');
|
||||||
const isLeft = is('left');
|
const isLeft = is('left');
|
||||||
@@ -826,6 +828,7 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
memoryMonitor.logMemory('[VideoPlayer] componentDidMount');
|
||||||
on('mousemove', this.activityDetected);
|
on('mousemove', this.activityDetected);
|
||||||
if (platform.touch) {
|
if (platform.touch) {
|
||||||
on('touchmove', this.activityDetected);
|
on('touchmove', this.activityDetected);
|
||||||
@@ -1021,6 +1024,7 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
memoryMonitor.logMemory('[VideoPlayer] componentWillUnmount - start cleanup', { src: this.props?.src });
|
||||||
// console.log('[VideoPlayer] componentWillUnmount - start cleanup', { src: this.props?.src });
|
// console.log('[VideoPlayer] componentWillUnmount - start cleanup', { src: this.props?.src });
|
||||||
off('mousemove', this.activityDetected);
|
off('mousemove', this.activityDetected);
|
||||||
if (platform.touch) {
|
if (platform.touch) {
|
||||||
@@ -1128,6 +1132,12 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
}
|
}
|
||||||
// 레퍼런스도 해제해 GC 대상이 되도록 함
|
// 레퍼런스도 해제해 GC 대상이 되도록 함
|
||||||
this.video = null;
|
this.video = null;
|
||||||
|
// 메모리 모니터링 인터벌 정리
|
||||||
|
if (this.memoryMonitoringInterval) {
|
||||||
|
clearInterval(this.memoryMonitoringInterval);
|
||||||
|
this.memoryMonitoringInterval = null;
|
||||||
|
}
|
||||||
|
memoryMonitor.logMemory('[VideoPlayer] componentWillUnmount - cleanup done');
|
||||||
// console.log('[VideoPlayer] componentWillUnmount - cleanup done', { src: this.props?.src });
|
// console.log('[VideoPlayer] componentWillUnmount - cleanup done', { src: this.props?.src });
|
||||||
if (this.floatingLayerController) {
|
if (this.floatingLayerController) {
|
||||||
this.floatingLayerController.unregister();
|
this.floatingLayerController.unregister();
|
||||||
@@ -1564,6 +1574,14 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
handleEvent = (ev) => {
|
handleEvent = (ev) => {
|
||||||
const el = this.video;
|
const el = this.video;
|
||||||
|
|
||||||
|
// 재생 종료 또는 오류 시 메모리 모니터링 타이머 정리
|
||||||
|
if (ev.type === 'ended' || ev.type === 'error') {
|
||||||
|
if (this.memoryMonitoringInterval) {
|
||||||
|
clearInterval(this.memoryMonitoringInterval);
|
||||||
|
this.memoryMonitoringInterval = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const updatedState = {
|
const updatedState = {
|
||||||
// Standard media properties
|
// Standard media properties
|
||||||
currentTime: 0,
|
currentTime: 0,
|
||||||
@@ -1798,6 +1816,11 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
play = () => {
|
play = () => {
|
||||||
|
console.log('[TEST] play() method called');
|
||||||
|
memoryMonitor.logMemory('[VideoPlayer] play() called', {
|
||||||
|
currentTime: this.state.currentTime,
|
||||||
|
duration: this.state.duration,
|
||||||
|
});
|
||||||
dlog('🟢 [PlayerPanel][VideoPlayer] play() called', {
|
dlog('🟢 [PlayerPanel][VideoPlayer] play() called', {
|
||||||
currentTime: this.state.currentTime,
|
currentTime: this.state.currentTime,
|
||||||
duration: this.state.duration,
|
duration: this.state.duration,
|
||||||
@@ -1819,6 +1842,21 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
this.send('play');
|
this.send('play');
|
||||||
this.announce($L('Play'));
|
this.announce($L('Play'));
|
||||||
this.startDelayedMiniFeedbackHide(5000);
|
this.startDelayedMiniFeedbackHide(5000);
|
||||||
|
// 재생 시작 시 정기적 메모리 모니터링 시작
|
||||||
|
if (!this.memoryMonitoringInterval) {
|
||||||
|
this.memoryMonitoringInterval = setInterval(() => {
|
||||||
|
try {
|
||||||
|
const mediaState = this.getMediaState();
|
||||||
|
memoryMonitor.logMemory('[VideoPlayer] Playing', {
|
||||||
|
currentTime: (mediaState?.currentTime ?? 0).toFixed(2),
|
||||||
|
duration: (mediaState?.duration ?? 0).toFixed(2),
|
||||||
|
buffered: (this.state?.proportionLoaded ?? 0).toFixed(2),
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
// 타이머 실행 중 오류 발생 시 무시
|
||||||
|
}
|
||||||
|
}, 30000); // 30초마다 메모리 확인
|
||||||
|
}
|
||||||
|
|
||||||
// Redux 상태 업데이트 - 재생 상태로 변경
|
// Redux 상태 업데이트 - 재생 상태로 변경
|
||||||
if (this.props.dispatch) {
|
if (this.props.dispatch) {
|
||||||
@@ -1842,6 +1880,10 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
pause = () => {
|
pause = () => {
|
||||||
|
memoryMonitor.logMemory('[VideoPlayer] pause() called', {
|
||||||
|
currentTime: this.state.currentTime.toFixed(2),
|
||||||
|
duration: this.state.duration.toFixed(2),
|
||||||
|
});
|
||||||
dlog('🔴 [VideoPlayer] pause() called', {
|
dlog('🔴 [VideoPlayer] pause() called', {
|
||||||
currentTime: this.state.currentTime,
|
currentTime: this.state.currentTime,
|
||||||
duration: this.state.duration,
|
duration: this.state.duration,
|
||||||
@@ -1863,6 +1905,11 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
this.send('pause');
|
this.send('pause');
|
||||||
this.announce($L('Pause'));
|
this.announce($L('Pause'));
|
||||||
this.stopDelayedMiniFeedbackHide();
|
this.stopDelayedMiniFeedbackHide();
|
||||||
|
// 재생 일시정지 시 정기적 메모리 모니터링 중지
|
||||||
|
if (this.memoryMonitoringInterval) {
|
||||||
|
clearInterval(this.memoryMonitoringInterval);
|
||||||
|
this.memoryMonitoringInterval = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Redux 상태 업데이트 - 일시정지 상태로 변경
|
// Redux 상태 업데이트 - 일시정지 상태로 변경
|
||||||
if (this.props.dispatch) {
|
if (this.props.dispatch) {
|
||||||
|
|||||||
191
com.twin.app.shoptime/src/utils/memoryMonitor.js
Normal file
191
com.twin.app.shoptime/src/utils/memoryMonitor.js
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
/**
|
||||||
|
* 메모리 모니터링 유틸리티
|
||||||
|
* [Memory] 태그를 붙인 로그로 메모리 사용량을 추적합니다
|
||||||
|
*/
|
||||||
|
|
||||||
|
let memoryMonitorInstance = null;
|
||||||
|
let initialized = false;
|
||||||
|
|
||||||
|
export const createMemoryMonitor = (enableInitLog = true) => {
|
||||||
|
// 싱글톤 패턴: 이미 생성된 인스턴스가 있으면 재사용
|
||||||
|
if (memoryMonitorInstance) {
|
||||||
|
return memoryMonitorInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableInitLog && !initialized) {
|
||||||
|
initialized = true;
|
||||||
|
const timestamp = new Date().toISOString();
|
||||||
|
console.log(`[Memory Monitor Initialized] ${timestamp}`);
|
||||||
|
if (typeof performance !== 'undefined' && performance.memory) {
|
||||||
|
console.log(`[Memory] API Support: YES - performance.memory available`);
|
||||||
|
} else {
|
||||||
|
console.log(`[Memory] API Support: NO - performance.memory NOT available (webOS TV 또는 제한된 브라우저)`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const getMemoryInfo = () => {
|
||||||
|
if (typeof performance !== 'undefined' && performance.memory) {
|
||||||
|
return {
|
||||||
|
usedJSHeapSize: (performance.memory.usedJSHeapSize / 1048576).toFixed(2),
|
||||||
|
totalJSHeapSize: (performance.memory.totalJSHeapSize / 1048576).toFixed(2),
|
||||||
|
jsHeapSizeLimit: (performance.memory.jsHeapSizeLimit / 1048576).toFixed(2),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatMemoryLog = (usedMB, totalMB, limitMB) => {
|
||||||
|
const percentage = ((usedMB / limitMB) * 100).toFixed(1);
|
||||||
|
return `[Memory] Used: ${usedMB}MB / Total: ${totalMB}MB / Limit: ${limitMB}MB (${percentage}%)`;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* 현재 메모리 상태를 로깅
|
||||||
|
* @param {string} context - 컨텍스트 설명
|
||||||
|
* @param {object} additionalInfo - 추가 정보
|
||||||
|
*/
|
||||||
|
logMemory: (context = '', additionalInfo = {}) => {
|
||||||
|
const mem = getMemoryInfo();
|
||||||
|
if (mem) {
|
||||||
|
const logMsg = formatMemoryLog(mem.usedJSHeapSize, mem.totalJSHeapSize, mem.jsHeapSizeLimit);
|
||||||
|
const info = Object.keys(additionalInfo).length > 0 ? JSON.stringify(additionalInfo) : '';
|
||||||
|
console.log(`${logMsg} | ${context} ${info}`);
|
||||||
|
} else {
|
||||||
|
const timestamp = new Date().toISOString();
|
||||||
|
console.log(`[Memory] [${timestamp}] ${context} - Browser does not support performance.memory API (추가정보: ${JSON.stringify(additionalInfo)})`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 메모리 사용량 변화를 추적
|
||||||
|
* @param {string} context - 컨텍스트 설명
|
||||||
|
* @param {number} previousMB - 이전 메모리 사용량 (MB)
|
||||||
|
* @returns {number} 현재 메모리 사용량 (MB)
|
||||||
|
*/
|
||||||
|
trackMemoryDelta: (context = '', previousMB = 0) => {
|
||||||
|
const mem = getMemoryInfo();
|
||||||
|
if (mem) {
|
||||||
|
const currentMB = parseFloat(mem.usedJSHeapSize);
|
||||||
|
const delta = (currentMB - previousMB).toFixed(2);
|
||||||
|
const deltaSign = delta > 0 ? '+' : '';
|
||||||
|
console.log(
|
||||||
|
`[Memory] ${context} | Current: ${currentMB}MB (${deltaSign}${delta}MB) | Total: ${mem.totalJSHeapSize}MB / Limit: ${mem.jsHeapSizeLimit}MB`
|
||||||
|
);
|
||||||
|
return currentMB;
|
||||||
|
}
|
||||||
|
return previousMB;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 정기적으로 메모리를 모니터링
|
||||||
|
* @param {number} intervalMs - 모니터링 간격 (기본값: 10000ms)
|
||||||
|
* @param {string} label - 모니터링 라벨
|
||||||
|
* @returns {function} cleanup 함수
|
||||||
|
*/
|
||||||
|
startPeriodicMonitoring: (intervalMs = 10000, label = 'Periodic') => {
|
||||||
|
let lastMemory = 0;
|
||||||
|
const mem = getMemoryInfo();
|
||||||
|
if (mem) lastMemory = parseFloat(mem.usedJSHeapSize);
|
||||||
|
|
||||||
|
const intervalId = setInterval(() => {
|
||||||
|
lastMemory = this.trackMemoryDelta(`${label}:`, lastMemory);
|
||||||
|
}, intervalMs);
|
||||||
|
|
||||||
|
return () => clearInterval(intervalId);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 버퍼 관련 메모리 정보 로깅
|
||||||
|
* @param {string} context - 컨텍스트
|
||||||
|
* @param {object} bufferInfo - 버퍼 정보 { bufferedSegments, totalDuration, etc }
|
||||||
|
*/
|
||||||
|
logBufferMemory: (context = '', bufferInfo = {}) => {
|
||||||
|
const mem = getMemoryInfo();
|
||||||
|
if (mem) {
|
||||||
|
const logMsg = formatMemoryLog(mem.usedJSHeapSize, mem.totalJSHeapSize, mem.jsHeapSizeLimit);
|
||||||
|
const bufferStr = JSON.stringify(bufferInfo);
|
||||||
|
console.log(`${logMsg} | Buffer: ${context} | Info: ${bufferStr}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HLS 상태에 따른 메모리 로깅
|
||||||
|
* @param {string} context - 컨텍스트
|
||||||
|
* @param {object} hlsState - HLS 상태 정보
|
||||||
|
*/
|
||||||
|
logHlsMemory: (context = '', hlsState = {}) => {
|
||||||
|
const mem = getMemoryInfo();
|
||||||
|
if (mem) {
|
||||||
|
const logMsg = formatMemoryLog(mem.usedJSHeapSize, mem.totalJSHeapSize, mem.jsHeapSizeLimit);
|
||||||
|
const hlsStr = JSON.stringify(hlsState);
|
||||||
|
console.log(`${logMsg} | HLS: ${context} | State: ${hlsStr}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 메모리 정보만 반환 (로깅 없음)
|
||||||
|
* @returns {object} 메모리 정보 객체
|
||||||
|
*/
|
||||||
|
getMemory: () => getMemoryInfo(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 싱글톤 인스턴스 저장
|
||||||
|
memoryMonitorInstance = {
|
||||||
|
logMemory: (context = '', additionalInfo = {}) => {
|
||||||
|
const mem = getMemoryInfo();
|
||||||
|
if (mem) {
|
||||||
|
const logMsg = formatMemoryLog(mem.usedJSHeapSize, mem.totalJSHeapSize, mem.jsHeapSizeLimit);
|
||||||
|
const info = Object.keys(additionalInfo).length > 0 ? JSON.stringify(additionalInfo) : '';
|
||||||
|
console.log(`${logMsg} | ${context} ${info}`);
|
||||||
|
} else {
|
||||||
|
const timestamp = new Date().toISOString();
|
||||||
|
console.log(`[Memory] [${timestamp}] ${context} - Browser does not support performance.memory API (추가정보: ${JSON.stringify(additionalInfo)})`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trackMemoryDelta: (context = '', previousMB = 0) => {
|
||||||
|
const mem = getMemoryInfo();
|
||||||
|
if (mem) {
|
||||||
|
const currentMB = parseFloat(mem.usedJSHeapSize);
|
||||||
|
const delta = (currentMB - previousMB).toFixed(2);
|
||||||
|
const deltaSign = delta > 0 ? '+' : '';
|
||||||
|
console.log(
|
||||||
|
`[Memory] ${context} | Current: ${currentMB}MB (${deltaSign}${delta}MB) | Total: ${mem.totalJSHeapSize}MB / Limit: ${mem.jsHeapSizeLimit}MB`
|
||||||
|
);
|
||||||
|
return currentMB;
|
||||||
|
}
|
||||||
|
return previousMB;
|
||||||
|
},
|
||||||
|
startPeriodicMonitoring: (intervalMs = 30000, label = 'Periodic') => {
|
||||||
|
let lastMemory = 0;
|
||||||
|
const mem = getMemoryInfo();
|
||||||
|
if (mem) lastMemory = parseFloat(mem.usedJSHeapSize);
|
||||||
|
|
||||||
|
const intervalId = setInterval(() => {
|
||||||
|
this.trackMemoryDelta(`${label}:`, lastMemory);
|
||||||
|
}, intervalMs);
|
||||||
|
|
||||||
|
return () => clearInterval(intervalId);
|
||||||
|
},
|
||||||
|
logBufferMemory: (context = '', bufferInfo = {}) => {
|
||||||
|
const mem = getMemoryInfo();
|
||||||
|
if (mem) {
|
||||||
|
const logMsg = formatMemoryLog(mem.usedJSHeapSize, mem.totalJSHeapSize, mem.jsHeapSizeLimit);
|
||||||
|
const bufferStr = JSON.stringify(bufferInfo);
|
||||||
|
console.log(`${logMsg} | Buffer: ${context} | Info: ${bufferStr}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
logHlsMemory: (context = '', hlsState = {}) => {
|
||||||
|
const mem = getMemoryInfo();
|
||||||
|
if (mem) {
|
||||||
|
const logMsg = formatMemoryLog(mem.usedJSHeapSize, mem.totalJSHeapSize, mem.jsHeapSizeLimit);
|
||||||
|
const hlsStr = JSON.stringify(hlsState);
|
||||||
|
console.log(`${logMsg} | HLS: ${context} | State: ${hlsStr}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getMemory: () => getMemoryInfo(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return memoryMonitorInstance;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createMemoryMonitor;
|
||||||
@@ -62,6 +62,7 @@ import css from './PlayerPanel.module.less';
|
|||||||
import PlayerTabButton from './PlayerTabContents/TabButton/PlayerTabButton';
|
import PlayerTabButton from './PlayerTabContents/TabButton/PlayerTabButton';
|
||||||
import TabContainer from './PlayerTabContents/TabContainer';
|
import TabContainer from './PlayerTabContents/TabContainer';
|
||||||
import TabContainerV2 from './PlayerTabContents/v2/TabContainer.v2';
|
import TabContainerV2 from './PlayerTabContents/v2/TabContainer.v2';
|
||||||
|
import createMemoryMonitor from '../../utils/memoryMonitor';
|
||||||
// import LiveShowContainer from './PlayerTabContents/v2/LiveShowContainer';
|
// import LiveShowContainer from './PlayerTabContents/v2/LiveShowContainer';
|
||||||
// import ShopNowContainer from './PlayerTabContents/v2/ShopNowContainer';
|
// import ShopNowContainer from './PlayerTabContents/v2/ShopNowContainer';
|
||||||
// import ShopNowButton from './PlayerTabContents/v2/ShopNowButton';
|
// import ShopNowButton from './PlayerTabContents/v2/ShopNowButton';
|
||||||
@@ -179,6 +180,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
const focusReturnRef = useRef(null);
|
const focusReturnRef = useRef(null);
|
||||||
const modalPrevRef = useRef(panelInfo?.modal);
|
const modalPrevRef = useRef(panelInfo?.modal);
|
||||||
const prevIsTopPanelDetailFromPlayerRef = useRef(false);
|
const prevIsTopPanelDetailFromPlayerRef = useRef(false);
|
||||||
|
const memoryMonitor = useRef(null);
|
||||||
const [playListInfo, setPlayListInfo] = USE_STATE('playListInfo', '');
|
const [playListInfo, setPlayListInfo] = USE_STATE('playListInfo', '');
|
||||||
const [shopNowInfo, setShopNowInfo] = USE_STATE('shopNowInfo');
|
const [shopNowInfo, setShopNowInfo] = USE_STATE('shopNowInfo');
|
||||||
const [backupInitialIndex, setBackupInitialIndex] = USE_STATE('backupInitialIndex', 0);
|
const [backupInitialIndex, setBackupInitialIndex] = USE_STATE('backupInitialIndex', 0);
|
||||||
@@ -370,6 +372,14 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
panelInfoRef.current = panelInfo;
|
panelInfoRef.current = panelInfo;
|
||||||
}, [panelInfo]);
|
}, [panelInfo]);
|
||||||
|
|
||||||
|
// memoryMonitor 초기화 (마운트 시 한 번만)
|
||||||
|
useEffect(() => {
|
||||||
|
if (!memoryMonitor.current) {
|
||||||
|
memoryMonitor.current = createMemoryMonitor(false); // 초기 로그 비활성화
|
||||||
|
console.log('[PlayerPanel] Memory monitor initialized');
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
// PlayerPanel.jsx의 라인 313-327 useEffect 수정 - detailPanelClosed flag 감지 추가
|
// PlayerPanel.jsx의 라인 313-327 useEffect 수정 - detailPanelClosed flag 감지 추가
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dlog('[PlayerPanel] 🔍 isOnTop useEffect 호출:', {
|
dlog('[PlayerPanel] 🔍 isOnTop useEffect 호출:', {
|
||||||
@@ -1733,6 +1743,24 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
setCurrentTime(videoPlayer.current?.getMediaState()?.currentTime);
|
setCurrentTime(videoPlayer.current?.getMediaState()?.currentTime);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'onBuffer': {
|
||||||
|
// 버퍼링 시작 시 메모리 상태 로깅
|
||||||
|
memoryMonitor.current.logMemory('[Video Buffer Start]', {
|
||||||
|
currentTime: videoPlayer.current?.getMediaState()?.currentTime?.toFixed(2),
|
||||||
|
duration: videoPlayer.current?.getMediaState()?.duration?.toFixed(2),
|
||||||
|
proportionLoaded: videoPlayer.current?.getMediaState()?.proportionLoaded?.toFixed(2),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'onBufferEnd': {
|
||||||
|
// 버퍼링 종료 시 메모리 상태 로깅
|
||||||
|
memoryMonitor.current.logMemory('[Video Buffer End]', {
|
||||||
|
currentTime: videoPlayer.current?.getMediaState()?.currentTime?.toFixed(2),
|
||||||
|
duration: videoPlayer.current?.getMediaState()?.duration?.toFixed(2),
|
||||||
|
proportionLoaded: videoPlayer.current?.getMediaState()?.proportionLoaded?.toFixed(2),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'error': {
|
case 'error': {
|
||||||
dispatch(
|
dispatch(
|
||||||
sendBroadCast({
|
sendBroadCast({
|
||||||
@@ -1746,6 +1774,23 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
const mediaId = videoPlayer.current?.video?.media?.mediaId;
|
const mediaId = videoPlayer.current?.video?.media?.mediaId;
|
||||||
setMediaId(mediaId);
|
setMediaId(mediaId);
|
||||||
setVideoLoaded(true);
|
setVideoLoaded(true);
|
||||||
|
// HLS 인스턴스 정보 로깅
|
||||||
|
try {
|
||||||
|
const hlsInstance = videoPlayer.current?.video?.getInternalPlayer?.('hls');
|
||||||
|
if (hlsInstance) {
|
||||||
|
memoryMonitor.current.logHlsMemory('[Video Loaded] HLS Instance', {
|
||||||
|
hlsVersion: hlsInstance.version,
|
||||||
|
config: {
|
||||||
|
maxBufferLength: hlsInstance.config?.maxBufferLength,
|
||||||
|
maxMaxBufferLength: hlsInstance.config?.maxMaxBufferLength,
|
||||||
|
backBufferLength: hlsInstance.config?.backBufferLength,
|
||||||
|
maxBufferSize: hlsInstance.config?.maxBufferSize,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// HLS 정보 수집 실패는 무시
|
||||||
|
}
|
||||||
dlog(
|
dlog(
|
||||||
'[PlayerPanel] 🎬 Video Loaded - shptmBanrTpNm:',
|
'[PlayerPanel] 🎬 Video Loaded - shptmBanrTpNm:',
|
||||||
panelInfoRef.current?.shptmBanrTpNm
|
panelInfoRef.current?.shptmBanrTpNm
|
||||||
@@ -1998,6 +2043,17 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
setVideoLoaded(false);
|
setVideoLoaded(false);
|
||||||
}, [currentPlayingUrl]);
|
}, [currentPlayingUrl]);
|
||||||
|
|
||||||
|
// 메모리 모니터링: 비디오 URL 변경 시
|
||||||
|
useEffect(() => {
|
||||||
|
if (currentPlayingUrl) {
|
||||||
|
memoryMonitor.current.logMemory(`[Video Change] New URL loaded`, {
|
||||||
|
url: currentPlayingUrl.substring(0, 50),
|
||||||
|
isHLS: currentPlayingUrl.includes('.m3u8'),
|
||||||
|
isDASH: currentPlayingUrl.includes('.mpd'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [currentPlayingUrl]);
|
||||||
|
|
||||||
// 비디오가 새로 선택될 때 타이머 초기화
|
// 비디오가 새로 선택될 때 타이머 초기화
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentPlayingUrl) {
|
if (currentPlayingUrl) {
|
||||||
|
|||||||
Reference in New Issue
Block a user