Dana
5 天以前 09de988e5f9223099f8a8e1f7f2b91b627ff839f
P1 录像:132541_学员C_1_58.mp4
P2 录像:132642_学员C_2_60.mp4
1个文件已修改
114 ■■■■■ 已修改文件
app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraRecordManager.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraRecordManager.java
@@ -6,6 +6,7 @@
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
import android.media.MediaMuxer;
import android.media.MediaRecorder;
import android.text.TextUtils;
@@ -83,6 +84,9 @@
    
    // 录制开始时间(纳秒),用于时间戳同步
    private volatile long recordingStartTimeNs = 0;
    // 刚完成的文件(用于重命名)
    private File completedVideoFile;
    
    /**
     * 录像回调接口
@@ -274,6 +278,13 @@
        
        stopRecordThread();
        releaseResources();
        // 重命名刚完成的文件(停止录像时)
        if (completedVideoFile != null) {
            renameCompletedFile(completedVideoFile);
            completedVideoFile = null;
        }
        if (usbCamera != null) {
            usbCamera.stopCamera();
        }
@@ -457,6 +468,11 @@
            mediaMuxer = null;
        }
        
        // 保存刚完成的文件路径,用于后续重命名
        if (currentVideoFile != null && currentVideoFile.exists()) {
            completedVideoFile = currentVideoFile;
        }
        muxerStarted = false;
        videoTrackIndex = -1;
        audioTrackIndex = -1;
@@ -557,6 +573,12 @@
                        // 释放当前资源
                        releaseResources();
                        
                        // 重命名刚完成的文件
                        if (completedVideoFile != null) {
                            renameCompletedFile(completedVideoFile);
                            completedVideoFile = null;
                        }
                        // 初始化新的编码器和Muxer
                        if (!initEncoderAndMuxer()) {
                            Timber.e("Failed to create new video file");
@@ -625,6 +647,13 @@
                }
                
                releaseResources();
                // 重命名刚完成的文件(停止录像时)
                if (completedVideoFile != null) {
                    renameCompletedFile(completedVideoFile);
                    completedVideoFile = null;
                }
                Timber.d("RecordThread ended");
            }
        }
@@ -699,6 +728,91 @@
    }
    
    /**
     * 重命名完成的视频文件
     * 格式:HHmmss_学员名_1或2_时长秒.mp4
     * 例如:132541_学员C_1_58.mp4
     */
    private void renameCompletedFile(File originalFile) {
        if (originalFile == null || !originalFile.exists()) {
            Timber.w("原始文件不存在,无法重命名: %s", originalFile);
            return;
        }
        try {
            // 1. 从原文件名提取时分秒(例如:132541_P1.mp4 -> 132541)
            String originalName = originalFile.getName();
            String timePart = originalName;
            // 移除 .mp4 扩展名
            if (originalName.endsWith(".mp4")) {
                timePart = originalName.substring(0, originalName.length() - 4);
            }
            // 移除 _P1 或 _P2 后缀
            if (timePart.endsWith("_P1") || timePart.endsWith("_P2")) {
                timePart = timePart.substring(0, timePart.length() - 3);
            }
            // 2. 获取学员名字
            String studentName = GlobalData.getInstance().parseWaterMaskInfo("student", "无", GlobalData.ShareType.STRING);
            if (TextUtils.isEmpty(studentName) || "无".equals(studentName)) {
                studentName = "学员";
            }
            // 3. 获取 P1/P2(1 对应 P1,2 对应 P2)
            int cameraId = (mediaArgu != null) ? mediaArgu.getUsbCameraId() : 1;
            String cameraIdStr = String.valueOf(cameraId);
            // 4. 获取视频时长(秒)
            int durationSeconds = getVideoDuration(originalFile);
            // 5. 构建新文件名:HHmmss_学员名_1或2_时长秒.mp4
            String newFileName = String.format("%s_%s_%s_%d.mp4", timePart, studentName, cameraIdStr, durationSeconds);
            File newFile = new File(originalFile.getParent(), newFileName);
            // 6. 重命名文件
            if (originalFile.renameTo(newFile)) {
                Timber.d("文件重命名成功: %s -> %s", originalFile.getName(), newFileName);
                // 更新回调中的文件名
                notifyCallback(2,0,newFileName);
            } else {
                Timber.e("文件重命名失败: %s -> %s", originalFile.getName(), newFileName);
            }
        } catch (Exception e) {
            Timber.e(e, "重命名文件时发生异常: %s", originalFile.getName());
        }
    }
    /**
     * 获取视频文件时长(秒)
     */
    private int getVideoDuration(File videoFile) {
        MediaMetadataRetriever retriever = null;
        try {
            retriever = new MediaMetadataRetriever();
            retriever.setDataSource(videoFile.getAbsolutePath());
            String durationStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
            if (durationStr != null && !durationStr.isEmpty()) {
                long durationMs = Long.parseLong(durationStr);
                int durationSeconds = (int) (durationMs / 1000);
                Timber.d("视频时长: %d 秒", durationSeconds);
                return durationSeconds;
            }
        } catch (Exception e) {
            Timber.e(e, "获取视频时长失败,使用默认值60秒");
        } finally {
            if (retriever != null) {
                try {
                    retriever.release();
                } catch (Exception e) {
                    Timber.e(e, "释放 MediaMetadataRetriever 失败");
                }
            }
        }
        // 如果获取失败,返回默认值60秒
        return 60;
    }
    /**
     * 检查并启动Muxer
     * P1模式:当视频和音频轨道都准备好时启动
     * P2模式:当视频轨道准备好时即可启动(无音频轨道)