feat:상세모달에 브라우저 내장 오디오 플레이어 추가
- DetailModal에 <audio> 태그 기반 재생기 추가 (다운로드 없이 바로 재생) - 다운로드 엔드포인트에 ?inline=1 파라미터 지원 (스트리밍 재생용) - Content-Length, Accept-Ranges 헤더 추가 - 플레이어 옆 다운로드 버튼 배치 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -229,7 +229,7 @@ public function status(int $id): JsonResponse
|
||||
/**
|
||||
* GCS 음성파일 다운로드
|
||||
*/
|
||||
public function download(int $id): Response|JsonResponse
|
||||
public function download(Request $request, int $id): Response|JsonResponse
|
||||
{
|
||||
$recording = AiVoiceRecording::find($id);
|
||||
|
||||
@@ -252,6 +252,7 @@ public function download(int $id): Response|JsonResponse
|
||||
|
||||
// 파일 확장자 추출
|
||||
$extension = pathinfo($recording->audio_file_path, PATHINFO_EXTENSION) ?: 'webm';
|
||||
$mimeType = 'audio/'.$extension;
|
||||
|
||||
// 파일명 생성 (한글 제목 지원)
|
||||
$title = $recording->title ?: 'recording';
|
||||
@@ -259,8 +260,12 @@ public function download(int $id): Response|JsonResponse
|
||||
$filename = $safeTitle.'.'.$extension;
|
||||
$encodedFilename = rawurlencode($filename);
|
||||
|
||||
$disposition = $request->query('inline') ? 'inline' : 'attachment';
|
||||
|
||||
return response($content)
|
||||
->header('Content-Type', 'audio/'.$extension)
|
||||
->header('Content-Disposition', "attachment; filename=\"{$encodedFilename}\"; filename*=UTF-8''{$encodedFilename}");
|
||||
->header('Content-Type', $mimeType)
|
||||
->header('Content-Length', strlen($content))
|
||||
->header('Accept-Ranges', 'bytes')
|
||||
->header('Content-Disposition', "{$disposition}; filename=\"{$encodedFilename}\"; filename*=UTF-8''{$encodedFilename}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -755,6 +755,23 @@ className={`flex-1 text-xs font-medium py-1.5 rounded-md transition-colors ${tab
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 오디오 플레이어 */}
|
||||
{data.audio_file_path && (
|
||||
<div className="px-6 py-3 bg-gray-50 border-b border-gray-100">
|
||||
<div className="flex items-center gap-3">
|
||||
<Icon name="volume-2" className="w-4 h-4 text-purple-500 flex-shrink-0" />
|
||||
<audio controls className="flex-1 h-9" style={{minWidth:0}}>
|
||||
<source src={`${API}/${data.id}/download?inline=1`} type="audio/webm" />
|
||||
</audio>
|
||||
<a href={`${API}/${data.id}/download`} download
|
||||
className="p-1.5 text-gray-400 hover:text-blue-600 hover:bg-blue-100 rounded-lg transition-colors flex-shrink-0"
|
||||
title="파일 다운로드">
|
||||
<Icon name="download" className="w-4 h-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Body */}
|
||||
<div className="flex-1 overflow-y-auto px-6 py-4">
|
||||
{data.status === 'PROCESSING' && (
|
||||
|
||||
Reference in New Issue
Block a user