import logging import uuid from rest_framework import viewsets, status from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.parsers import MultiPartParser, FormParser from django.conf import settings from .models import TranscriptionTask from .serializers import TranscriptionTaskSerializer from .services import AliyunTingwuService logger = logging.getLogger(__name__) class TranscriptionTaskViewSet(viewsets.ModelViewSet): queryset = TranscriptionTask.objects.all() serializer_class = TranscriptionTaskSerializer parser_classes = (MultiPartParser, FormParser) def create(self, request, *args, **kwargs): """ 上传音频文件并创建听悟转写任务 """ file_obj = request.FILES.get('file') if not file_obj: return Response({'error': '未提供文件'}, status=status.HTTP_400_BAD_REQUEST) service = AliyunTingwuService() if not service.bucket or not service.client: return Response({'error': '阿里云服务未配置'}, status=status.HTTP_503_SERVICE_UNAVAILABLE) try: # 1. 上传文件到 OSS file_extension = file_obj.name.split('.')[-1] file_name = f"transcription/{uuid.uuid4()}.{file_extension}" # 使用服务上传 oss_url = service.upload_to_oss(file_obj, file_name) # 2. 创建数据库记录 task_record = TranscriptionTask.objects.create( file_url=oss_url, status=TranscriptionTask.Status.PENDING ) # 3. 调用听悟接口创建任务 try: tingwu_response = service.create_transcription_task(oss_url) task_id = tingwu_response.get('TaskId') if task_id: task_record.task_id = task_id task_record.status = TranscriptionTask.Status.PROCESSING task_record.save() else: task_record.status = TranscriptionTask.Status.FAILED task_record.error_message = "未能获取 TaskId" task_record.save() return Response({'error': '未能获取 TaskId'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) except Exception as e: task_record.status = TranscriptionTask.Status.FAILED task_record.error_message = str(e) task_record.save() logger.error(f"创建听悟任务失败: {e}") return Response({'error': f"创建听悟任务失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) serializer = self.get_serializer(task_record) return Response(serializer.data, status=status.HTTP_201_CREATED) except Exception as e: logger.error(f"处理上传请求失败: {e}") return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) @action(detail=True, methods=['get']) def refresh_status(self, request, pk=None): """ 刷新任务状态并获取结果 """ task = self.get_object() # 如果任务已经完成或失败,直接返回当前状态 if task.status in [TranscriptionTask.Status.SUCCEEDED, TranscriptionTask.Status.FAILED]: serializer = self.get_serializer(task) return Response(serializer.data) if not task.task_id: return Response({'error': '任务ID不存在'}, status=status.HTTP_400_BAD_REQUEST) service = AliyunTingwuService() try: result = service.get_task_info(task.task_id) task_status = result.get('TaskStatus') if task_status == 'COMPLETE': task.status = TranscriptionTask.Status.SUCCEEDED # 解析结果 task_result = result.get('Result', {}) # 提取逐字稿 sentences = task_result.get('Transcription', {}).get('Sentences', []) full_text = " ".join([s.get('Text', '') for s in sentences]) task.transcription = full_text # 提取总结 # 总结结果结构可能因配置不同而异,这里尝试获取摘要 summarization = task_result.get('Summarization', {}) # 听悟的总结通常在 Summarization.Text 或类似字段 # 如果是章节摘要,可能在 Chapters 中 # 假设是全文摘要 if 'Text' in summarization: task.summary = summarization['Text'] elif 'Headline' in summarization: task.summary = summarization['Headline'] else: # 尝试从章节摘要中提取 chapters = task_result.get('Chapters', []) summary_parts = [] for chapter in chapters: if 'Headline' in chapter: summary_parts.append(chapter['Headline']) if 'Summary' in chapter: summary_parts.append(chapter['Summary']) task.summary = "\n".join(summary_parts) task.save() elif task_status == 'FAILED': task.status = TranscriptionTask.Status.FAILED task.error_message = result.get('TaskStatusText', 'Unknown error') task.save() # 其他状态 (PENDING, RUNNING) 不做更改 serializer = self.get_serializer(task) return Response(serializer.data) except Exception as e: logger.error(f"刷新任务状态失败: {e}") return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)