@@ -55,6 +55,24 @@ function toCivilization(value: string): Civilization {
5555 return VALID_CIVILIZATIONS . has ( value ) ? ( value as Civilization ) : 'Other' ;
5656}
5757
58+ /**
59+ * "이건 뭐야?" 계열 키워드 감지.
60+ * 카메라 열린 상태에서 이 패턴이 감지되면 자동 캡처 트리거.
61+ */
62+ const WHAT_IS_THIS_PATTERNS = [
63+ // Korean: "이거/이건/이게" + "뭐야/뭐지/뭔지/뭘까"
64+ / 이 (?: 거 | 건 | 게 ) \s * 뭐 / ,
65+ / 뭐 (?: 야 | 지 ) \s * 이 (?: 거 | 건 | 게 ) / ,
66+ / 이 (?: 거 | 건 | 게 ) \s * (?: 뭔 | 뭘 ) / ,
67+ // English
68+ / w h a t (?: ' s | i s ) t h i s / i,
69+ / w h a t (?: ' s | i s ) t h a t / i,
70+ ] ;
71+
72+ function isWhatIsThisQuery ( text : string ) : boolean {
73+ return WHAT_IS_THIS_PATTERNS . some ( ( pattern ) => pattern . test ( text ) ) ;
74+ }
75+
5876// ── 이벤트 핸들러 팩토리 ────────────────────────────────────
5977
6078interface SessionRefs {
@@ -65,6 +83,9 @@ interface SessionRefs {
6583 currentArtifact : React . RefObject < ArtifactSummary | null > ;
6684 reconnect : React . RefObject < ReconnectManager | null > ;
6785 geoCoords : React . RefObject < { lat : number ; lng : number } > ;
86+ cameraCapture : React . RefObject < CameraCapture | null > ;
87+ isCameraOpen : React . RefObject < boolean > ;
88+ lastAutoCaptureTime : React . RefObject < number > ;
6889}
6990
7091interface SessionSetters {
@@ -168,6 +189,19 @@ function createSessionEvents(refs: SessionRefs, setters: SessionSetters): LiveSe
168189 const cleaned = cleanSttText ( data . text ) ;
169190 if ( ! cleaned ) return ;
170191
192+ // "이건 뭐야?" 감지 → 카메라 열려있으면 자동 캡처 (5초 쿨다운)
193+ if (
194+ refs . isCameraOpen . current &&
195+ isWhatIsThisQuery ( cleaned ) &&
196+ Date . now ( ) - refs . lastAutoCaptureTime . current > 5000
197+ ) {
198+ const photo = refs . cameraCapture . current ?. capturePhoto ( ) ;
199+ if ( photo ) {
200+ refs . lastAutoCaptureTime . current = Date . now ( ) ;
201+ refs . liveSession . current ?. sendPhoto ( photo , cleaned ) ;
202+ }
203+ }
204+
171205 setters . setTranscript ( prev => {
172206 const last = prev [ prev . length - 1 ] ;
173207 // 같은 유저 턴이면 이어붙이기 (3초 내)
@@ -338,6 +372,8 @@ export function useLiveSession(): UseLiveSessionReturn {
338372 const currentArtifactRef = useRef < ArtifactSummary | null > ( null ) ;
339373 const userIdRef = useRef < string > ( '' ) ;
340374 const geoCoordsRef = useRef < { lat : number ; lng : number } > ( { lat : 0 , lng : 0 } ) ;
375+ const isCameraOpenRef = useRef ( false ) ;
376+ const lastAutoCaptureTimeRef = useRef ( 0 ) ;
341377
342378 // 브라우저 Geolocation으로 좌표 추적
343379 useEffect ( ( ) => {
@@ -415,6 +451,9 @@ export function useLiveSession(): UseLiveSessionReturn {
415451 currentArtifact : currentArtifactRef ,
416452 reconnect : reconnectRef ,
417453 geoCoords : geoCoordsRef ,
454+ cameraCapture : cameraCaptureRef ,
455+ isCameraOpen : isCameraOpenRef ,
456+ lastAutoCaptureTime : lastAutoCaptureTimeRef ,
418457 } ;
419458 const setters : SessionSetters = {
420459 setSessionState, setTranscript, setCurrentArtifact,
@@ -516,8 +555,8 @@ export function useLiveSession(): UseLiveSessionReturn {
516555 } , [ ] ) ;
517556
518557 const toggleCamera = useCallback ( ( enabled : boolean ) => {
519- // 카메라 ON/OFF는 프리뷰만 제어 — 프레임 스트리밍 없음
520- // 인식은 캡처 버튼(sendPhoto)으로만 트리거
558+ isCameraOpenRef . current = enabled ;
559+ // 카메라 ON/OFF는 프리뷰만 제어 — 인식은 캡처 버튼(sendPhoto)으로만 트리거
521560 if ( ! enabled ) {
522561 cameraCaptureRef . current ?. stopFrameLoop ( ) ;
523562 }
0 commit comments