diff --git a/apps/api/src/entity/summary.entity.ts b/apps/api/src/entity/summary.entity.ts index db14a8fd..58dd928d 100644 --- a/apps/api/src/entity/summary.entity.ts +++ b/apps/api/src/entity/summary.entity.ts @@ -17,7 +17,7 @@ export class Summary { @Column('varchar') audioUrl: string; - @Column('json', { nullable: true }) + @Column('text', { nullable: true }) summaryText: string[]; @CreateDateColumn({ type: 'timestamp', name: 'created_at' }) diff --git a/apps/api/src/stream/stream.controller.ts b/apps/api/src/stream/stream.controller.ts index 9d00f36f..84997326 100644 --- a/apps/api/src/stream/stream.controller.ts +++ b/apps/api/src/stream/stream.controller.ts @@ -19,7 +19,7 @@ export class StreamController { @Get('summary/:ticleId') async getSummaryByTicleId(@Param('ticleId') ticleId: number) { - const text = await this.streamService.getSummaryText(ticleId); - return { summary: text }; + const summary = await this.streamService.getSummary(ticleId); + return summary; } } diff --git a/apps/api/src/stream/stream.service.ts b/apps/api/src/stream/stream.service.ts index 77e1924f..4e9bfb6e 100644 --- a/apps/api/src/stream/stream.service.ts +++ b/apps/api/src/stream/stream.service.ts @@ -103,11 +103,12 @@ export class StreamService { } } - async getSummaryText(ticleId: number) { + async getSummary(ticleId: number) { const summary = await this.summaryRepository.findOne({ where: { ticle: { id: ticleId } }, }); - return summary.summaryText; + + return summary; } async updateSummaryText(summary: Summary, summaryText: string[]) { diff --git a/apps/web/src/components/dashboard/AiSummaryDialog.tsx b/apps/web/src/components/dashboard/AiSummaryDialog.tsx index 34bd5a65..70573089 100644 --- a/apps/web/src/components/dashboard/AiSummaryDialog.tsx +++ b/apps/web/src/components/dashboard/AiSummaryDialog.tsx @@ -17,15 +17,23 @@ function AiSummaryDialog({ isOpen, onClose, ticleId }: AiSummaryDialogProps) { AI 음성 요약 - {!data || data?.summary.length === 0 ? ( + {!data && (
AI 요약을 처리중이에요.
- ) : ( -

{data?.summary[0]}

+ )} + {data && !data.summaryText && ( +
+ + AI 요약 결과가 없어요. + +
+ )} + {data && data.summaryText && ( +

{data.summaryText}

)}
diff --git a/apps/web/src/components/live/SettingDialog/SelectMedia.tsx b/apps/web/src/components/live/SettingDialog/SelectMedia.tsx index 78152dfe..73fb42f4 100644 --- a/apps/web/src/components/live/SettingDialog/SelectMedia.tsx +++ b/apps/web/src/components/live/SettingDialog/SelectMedia.tsx @@ -18,7 +18,7 @@ function SelectMedia() { stream?.getTracks().forEach((track) => track.stop()); - const cameraStream = await getCameraStream({ video: { deviceId: selectedVideoDeviceId } }); + const cameraStream = await getCameraStream({ deviceId: selectedVideoDeviceId }); videoRef.current.srcObject = cameraStream; @@ -28,6 +28,12 @@ function SelectMedia() { getStream(); }, [selectedVideoDeviceId]); + useEffect(() => { + return () => { + stream?.getTracks().forEach((track) => track.stop()); + }; + }, [stream]); + return (
diff --git a/apps/web/src/hooks/useMediaTracks.ts b/apps/web/src/hooks/useMediaTracks.ts index 53bb6f09..41c7787c 100644 --- a/apps/web/src/hooks/useMediaTracks.ts +++ b/apps/web/src/hooks/useMediaTracks.ts @@ -31,18 +31,11 @@ const useMediaTracks = () => { ); const getCameraTrack = async () => { - if (!selectedVideoDeviceId) { - return; - } + const options = selectedVideoDeviceId ? { deviceId: selectedVideoDeviceId } : {}; - const stream = await getCameraStream({ - video: { deviceId: selectedVideoDeviceId }, - }); + const stream = await getCameraStream(options); const track = stream.getVideoTracks()[0]; - - if (!track) { - return; - } + if (!track) return; setVideo({ stream, paused: true }); @@ -50,24 +43,13 @@ const useMediaTracks = () => { }; const getAudioTrack = async () => { - if (!selectedAudioDeviceId) { - return; - } + const options = selectedAudioDeviceId ? { deviceId: selectedAudioDeviceId } : {}; - const stream = await getMicStream({ - audio: { - deviceId: { - exact: selectedAudioDeviceId, - ideal: selectedAudioDeviceId, - }, - }, - }); + const stream = await getMicStream(options); const track = stream.getAudioTracks()[0]; - if (!track) { - return; - } + if (!track) return; setAudio({ stream, paused: true }); @@ -83,9 +65,7 @@ const useMediaTracks = () => { const track = stream.getVideoTracks()[0]; - if (!track) { - return; - } + if (!track) return; setScreen({ stream, paused: false }); diff --git a/apps/web/src/utils/stream.ts b/apps/web/src/utils/stream.ts index 9bcb4440..948f743e 100644 --- a/apps/web/src/utils/stream.ts +++ b/apps/web/src/utils/stream.ts @@ -19,7 +19,7 @@ const DEFAULT_SCREEN_CONSTRAINTS: MediaTrackConstraints = { frameRate: { max: 30, ideal: 15 }, }; -const getCameraStream = async (options: MediaStreamConstraints = {}) => { +const getCameraStream = async (options: MediaTrackConstraints = {}) => { return navigator.mediaDevices.getUserMedia({ video: { ...DEFAULT_VIDEO_CONSTRAINTS, @@ -28,7 +28,7 @@ const getCameraStream = async (options: MediaStreamConstraints = {}) => { }); }; -const getMicStream = async (options: MediaStreamConstraints = {}) => { +const getMicStream = async (options: MediaTrackConstraints = {}) => { return navigator.mediaDevices.getUserMedia({ audio: { ...DEFAULT_AUDIO_CONSTRAINTS, @@ -37,7 +37,7 @@ const getMicStream = async (options: MediaStreamConstraints = {}) => { }); }; -const getScreenStream = async (options: MediaStreamConstraints = {}) => { +const getScreenStream = async (options: MediaTrackConstraints = {}) => { return navigator.mediaDevices.getDisplayMedia({ video: { ...DEFAULT_SCREEN_CONSTRAINTS, diff --git a/packages/types/src/dashboard/getDashboardList.ts b/packages/types/src/dashboard/getDashboardList.ts index 23363e3c..0c1349db 100644 --- a/packages/types/src/dashboard/getDashboardList.ts +++ b/packages/types/src/dashboard/getDashboardList.ts @@ -62,8 +62,13 @@ export const DashboardApplicantsResponseSchema = z.array( export type DashboardApplicantsResponse = z.infer; -export const DashboardAiSummaryResponseSchema = z.object({ - summary: z.array(z.string()), -}); +export const DashboardAiSummaryResponseSchema = z + .object({ + id: z.number(), + summaryText: z.string().nullable(), + audioUrl: z.string(), + createdAt: z.string().datetime(), + }) + .nullable(); export type DashboardAiSummaryResponse = z.infer;