视频保存

This commit is contained in:
duoaohui
2026-05-19 15:28:36 +08:00
parent 8e5770eb5d
commit c1c108e632
5 changed files with 35 additions and 8 deletions

View File

@@ -47,6 +47,7 @@ type MeetingRecordingService struct {
minioClient *minio.Client
minioCfg *config.MinioConfig
meetingCfg *config.MeetingConfig
}
// NewMeetingRecordingService Wire Provider
@@ -59,6 +60,7 @@ func NewMeetingRecordingService(
mediaOrchestrator MediaOrchestrator,
minioClient *minio.Client,
minioCfg *config.MinioConfig,
meetingCfg *config.MeetingConfig,
) *MeetingRecordingService {
return &MeetingRecordingService{
roomDAO: roomDAO,
@@ -69,6 +71,7 @@ func NewMeetingRecordingService(
mediaOrchestrator: mediaOrchestrator,
minioClient: minioClient,
minioCfg: minioCfg,
meetingCfg: meetingCfg,
}
}
@@ -510,6 +513,11 @@ func (s *MeetingRecordingService) prepareUploadArtifact(ctx context.Context, web
if webmPath == "" {
return webmPath, ".webm", "video/webm", ""
}
if s.meetingCfg == nil || !s.meetingCfg.RecordingTranscodeEnabled {
logs.Info(ctx, funcName, "录制转码未启用,直接上传 webm",
zap.Int64("recording_id", recordingID), zap.String("webm_path", webmPath))
return webmPath, ".webm", "video/webm", ""
}
mp4Path, err := s.transcodeWebmToMp4(ctx, webmPath)
if err != nil {
@@ -535,16 +543,26 @@ func (s *MeetingRecordingService) prepareUploadArtifact(ctx context.Context, web
// - -movflags +faststartmoov 前置HTTP Range 即点即播
// - -y覆盖目标文件避免重复 stop 时 EEXIST
func (s *MeetingRecordingService) transcodeWebmToMp4(ctx context.Context, webmPath string) (string, error) {
if _, err := exec.LookPath("ffmpeg"); err != nil {
ffmpegPath := "ffmpeg"
timeoutSec := 600
if s.meetingCfg != nil {
if strings.TrimSpace(s.meetingCfg.RecordingTranscodeFFmpegPath) != "" {
ffmpegPath = strings.TrimSpace(s.meetingCfg.RecordingTranscodeFFmpegPath)
}
if s.meetingCfg.RecordingTranscodeTimeoutSecond > 0 {
timeoutSec = s.meetingCfg.RecordingTranscodeTimeoutSecond
}
}
if _, err := exec.LookPath(ffmpegPath); err != nil {
return "", fmt.Errorf("ffmpeg 未安装或不在 PATH: %w", err)
}
mp4Path := strings.TrimSuffix(webmPath, filepath.Ext(webmPath)) + ".mp4"
// 转码上限:单文件最长容忍 10 分钟 CPU 时间,超时则视为失败回退
tctx, cancel := context.WithTimeout(ctx, 10*time.Minute)
tctx, cancel := context.WithTimeout(ctx, time.Duration(timeoutSec)*time.Second)
defer cancel()
cmd := exec.CommandContext(tctx, "ffmpeg",
cmd := exec.CommandContext(tctx, ffmpegPath,
"-y",
"-i", webmPath,
"-c:v", "libx264", "-preset", "veryfast", "-crf", "23",

View File

@@ -111,15 +111,15 @@ func InitializeApp(cfg *config.Config) (*App, error) {
meetingRecordingDAO := dao6.NewMeetingRecordingDAO(gormDB)
meetingBroadcaster := service7.NewMeetingBroadcaster(meetingParticipantDAO, pubSub)
httpMediaOrchestrator := service7.NewHTTPMediaOrchestrator(cfg, client)
meetingConfig := provideMeetingConfig(cfg)
meetingLifecycleService := service7.NewMeetingLifecycleService(meetingRoomDAO, meetingParticipantDAO, client, meetingBroadcaster, httpMediaOrchestrator, cfg)
meetingService := service7.NewMeetingService(meetingRoomDAO, meetingParticipantDAO, meetingChatDAO, gormDB, client, meetingBroadcaster, notifyService, friendshipDAO, onlineService, httpMediaOrchestrator, meetingLifecycleService)
meetingSignalService := service7.NewMeetingSignalService(meetingRoomDAO, meetingParticipantDAO, client, meetingBroadcaster, httpMediaOrchestrator, meetingLifecycleService)
meetingRecordingService := service7.NewMeetingRecordingService(meetingRoomDAO, meetingParticipantDAO, meetingRecordingDAO, client, meetingBroadcaster, httpMediaOrchestrator, minioClient, minioConfig)
meetingRecordingService := service7.NewMeetingRecordingService(meetingRoomDAO, meetingParticipantDAO, meetingRecordingDAO, client, meetingBroadcaster, httpMediaOrchestrator, minioClient, minioConfig, meetingConfig)
// admin 会议管理服务在 recording service 构造后再创建,从而支持"强制结束录制"兜底
meetingManageService := service2.NewMeetingManageService(meetingManageDAO, meetingRecordingService)
meetingManageController := controller2.NewMeetingManageController(meetingManageService)
meetingController := controller7.NewMeetingController(meetingService)
meetingConfig := provideMeetingConfig(cfg)
meetingRecordingController := controller7.NewMeetingRecordingController(meetingRecordingService, meetingConfig)
meetingWSHandler := controller7.NewMeetingWSHandler(meetingSignalService, hub)
meetingCleanupTask := task2.NewMeetingCleanupTask(meetingLifecycleService, meetingRoomDAO, meetingChatDAO)