Java 视频处理:基于 MD5 校验秒传及 ffmpeg 切片合并的实现

news2025/2/28 21:19:11

本文介绍两种网络技术实现方法。一是 MD5 校验秒传,服务器端用数据库记上传文件 MD5 值及存储路径,Java 代码接收客户端 MD5 值并查询校验,返回状态码。二是用 ffmpeg 切片视频成 m3u8 上传,异步合并文件实现视频按需加载。
在这里插入图片描述

1. 通过MD5校验实现秒传

服务器端MD5校验

  1. 数据库存储
    服务器端需数据库(如 MySQL、MongoDB 等)记录上传文件 MD5 值及存储路径。以 MySQL 为例,创建简单表存储相关信息。表结构中,md5_value存文件 MD5 值,file_path存服务器端存储路径,upload_time记录文件上传时间。
CREATE TABLE uploaded_files (
    id INT AUTO_INCREMENT PRIMARY KEY,
    md5_value VARCHAR(32) NOT NULL UNIQUE,
    file_path VARCHAR(255) NOT NULL,
    upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
  1. 校验逻辑实现
    Java服务器端代码示例:接收客户端 MD5 值并校验(用 Spring Boot 框架简化示例,实际应用可依具体框架和需求调整)。代码中接收客户端传来的 MD5 值在数据库查询校验。查到记录则文件已存在,返回 200 状态码表示秒传成功;未查到返回 404 表示需正常上传;查询出错返回 500 表示服务器内部错误。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@SpringBootApplication
@RestController
public class FileServerApp {

    private static final String JDBC_URL = "jdbc:mysql://localhost:3306/your_database_name?useSSL=false&serverTimezone=UTC";
    private static final String JDBC_USERNAME = "your_username";
    private static final String JDBC_PASSWORD = "your_password";

    public static void main(String[] args) {
        SpringApplication.run(FileServerApp.class, args);
    }

    @GetMapping("/checkFile")
    public ResponseEntity<String> checkFile(@RequestParam("md5") String md5) {
        try (Connection connection = DriverManager.getConnection(JDBC_URL, JDBC_USERNAME, JDBC_PASSWORD);
             PreparedStatement preparedStatement = connection.prepareStatement("SELECT file_path FROM uploaded_files WHERE md5_value =?")) {

            preparedStatement.setString(1, md5);
            ResultSet resultSet = preparedStatement.executeQuery();

            if (resultSet.next()) {
                // 文件已存在,返回200状态码
                return new ResponseEntity<>("文件已存在", HttpStatus.OK);
            } else {
                // 文件不存在,返回404状态码
                return new ResponseEntity<>("文件不存在", HttpStatus.NOT_FOUND);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            // 数据库查询出错,返回500状态码
            return new ResponseEntity<>("服务器内部错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}

2. 用 ffmpeg 将视频切片成 m3u8 上传,采用异步合并文件实现视频按需加载

视频切割

  1. 参数调整
    前面切割视频示例仅设常见参数,如视频编码格式(-c:v libx264)、音频编码格式(-c:a aac)、切片时长(-hls_time 10)和列表大小(-hls_list_size 0)。实际应用中或需依具体需求调整这些参数,比如:

    • 视频分辨率:要支持多种分辨率视频播放,可添加不同参数设置生成不同分辨率视频切片集合,在 m3u8 文件中组织,实现自适应分辨率播放。如添加-s:v 1280x720-s:v 640x360等参数分别生成高清和标清视频切片。
    • 码率设置:根据网络状况和目标设备性能,需设置不同视频码率,可通过参数如-b:v 2000k实现不同码率视频切片生成。
  2. 错误处理细化
    仅依process.waitFor()返回值判断切割不足。实际应用中应获取ffmpeg执行输出信息定位问题。以下是修改后示例,读取ffmpeg标准输出和错误输出信息处理切割问题。

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class VideoSliceUtil {
    public static void sliceVideo(File videoFile, String outputDir) {
        try {
            String ffmpegPath = "ffmpeg"; // 根据实际安装路径修改
            String command = ffmpegPath + " -i " + videoFile.getAbsolutePath() + " -c:v libx264 -c:a aac -f hls -hls_time 10 -hls_list_size 0 " + outputDir + "/video.m3u8";
            Process process = Runtime.getRuntime().exec(command);

            // 读取标准输出和标准错误输出信息
            InputStream stdout = process.getInputStream();
            InputStream stderr = process.getErrorStream();

            BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout));
            BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr));

            List<String> stdoutMessages = new ArrayList<>();
            List<String> stderrMessages = new ArrayList<>();

            String line;
            while ((line = stdoutReader.readLine())!= null) {
                stdoutMessages.add(line);
            }
            while ((line = stderrReader.readLine())!= null) {
                stderrMessages.add(line);
            }

            int exitCode = process.waitFor();

            if (exitCode == 0) {
                System.out.println("视频切割成功");
                if (!stdoutMessages.isEmpty()) {
                    System.out.println("标准输出信息:");
                    for (String msg : stdoutMessages) {
                        System.out.println(msg);
                    }
                }
            } else {
                System.out.println("视频切割失败");
                if (!stderrMessages.isEmpty()) {
                    System.out.println("标准错误输出信息:");
                    for (String msg : stderrMessages) {
                        System.out.println(msg);
                    }
                }
            }

            // 关闭流
            stdoutReader.close();
            stderrReader.close();
            stdout.close();
            stderr.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

异步合并文件

  1. 具体合并逻辑实现
    使用FFmpegFrameRecorder库合并视频片段。假设切割所得片段在指定目录且 m3u8 文件已正确生成。先创建FFmpegFrameRecorder对象,设置视频、音频编码格式及输出文件格式。遍历视频片段,用FrameGrabber读取帧,通过recorder记录到合并文件中。
import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.ffmpeg.global.swscale;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.OpenCVFrameGrabber;

public class FileMergeAsync {
    public static void mergeFilesAsync(final File[] filesToMerge, final String outputFile) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    // 创建FFmpegFrameRecorder对象用于合并视频
                    FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, -1);
                    recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
                    recorder.setAudioCodec(avutil.AV_CODEC_ID_AAC);
                    recorder.setFormat("mp4");
                    recorder.start();

                    // 遍历每个视频片段进行合并
                    for (File file : filesToMerge) {
                        FrameGrabber grabber = new OpenCVFrameGrabber(file);
                        grabber.start();

                        Frame frame;
                        while ((frame = grabber.read())!= null) {
                            recorder.record(frame);
                        }

                        grabber.stop();
                    }

                    recorder.stop();

                    System.out.println("文件合并成功");
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("文件合并失败");
                } finally {
                    executor.shutdown();
                }
            }
        });
    }
}
  1. 资源管理与优化
    合并文件时涉及多个对象创建与使用,如FFmpegFrameRecorderFrameGrabber等,需注意资源管理与优化。用后及时调用stop()释放资源,避免内存泄漏。对可能的异常,在异常处理代码中正确关闭和释放资源。

  2. 异步处理的监控与反馈
    前面异步合并文件示例仅提交任务后打印成功或失败消息。实际应用中需对异步任务深入监控并提供更多反馈。可通过添加回调函数或用异步任务监控框架了解进度、异常等情况并反馈给相关方。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2278807.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文读懂iOS中的Crash捕获、分析以及防治

Crash系统性总结 Crash捕获与分析Crash收集符号化分析 Crash类别以及解法分析子线程访问UI而导致的崩溃unrecognized selector send to instance xxxKVO crashKVC造成的crashNSTimer导致的Crash野指针Watch Dog超时造成的crash其他crash待补充 参考文章&#xff1a; 对于iOS端开…

RK3576 Android14 状态栏和导航栏增加显示控制功能

问题背景&#xff1a; 因为RK3576 Android14用户需要手动控制状态栏和导航栏显示隐藏控制&#xff0c;包括对锁屏后下拉状态栏的屏蔽&#xff0c;在设置功能里增加此功能的控制&#xff0c;故参考一些博客完成此功能&#xff0c;以下是具体代码路径的修改内容。 解决方案&…

【Rust自学】13.5. 迭代器 Pt.1:迭代器的定义、iterator trait和next方法

13.5.0. 写在正文之前 Rust语言在设计过程中收到了很多语言的启发&#xff0c;而函数式编程对Rust产生了非常显著的影响。函数式编程通常包括通过将函数作为值传递给参数、从其他函数返回它们、将它们分配给变量以供以后执行等等。 在本章中&#xff0c;我们会讨论 Rust 的一…

LabVIEW 蔬菜精密播种监测系统

在当前蔬菜播种工作中&#xff0c;存在着诸多问题。一方面&#xff0c;播种精度难以达到现代农业的高标准要求&#xff0c;导致种子分布不均&#xff0c;影响作物的生长发育和最终产量&#xff1b;另一方面&#xff0c;对于小粒径种子&#xff0c;传统的监测手段难以实现有效监…

2024年年终总结——坎坷与坚持,焦虑与收获

不知不觉间&#xff0c;2024年已经悄然过去&#xff0c;回望这一年的时间&#xff0c;一时间竟感觉混混沌沌无法形容&#xff0c;选择一些时间坐下来让自己简单回忆一下自己的2024。 先简单回望一下24年一整年的工作情况&#xff1a; 24年一开始&#xff0c;工作最期待的的节点…

无人机技术架构剖析!

一、飞机平台系统 飞机平台系统是无人机飞行的主体平台&#xff0c;主要提供飞行能力和装载功能。它由机体结构、动力装置、电气设备等组成。 机体结构&#xff1a;无人机的机身是其核心结构&#xff0c;承载着其他各个组件并提供稳定性。常见的机身材料包括碳纤维、铝合金、…

springboot基于微信小程序的传统美食文化宣传平台小程序

Spring Boot 基于微信小程序的传统美食文化宣传平台 一、平台概述 Spring Boot 基于微信小程序的传统美食文化宣传平台是一个集传统美食展示、文化传承、美食制作教程分享、用户互动交流以及美食相关活动推广为一体的综合性线上平台。它借助 Spring Boot 强大的后端开发框架构…

Android系统开发(八):从麦克风到扬声器,音频HAL框架的奇妙之旅

引言&#xff1a;音浪太强&#xff0c;我稳如老 HAL&#xff01; 如果有一天你的耳机里传来的不是《咱们屯里人》&#xff0c;而是金属碰撞般的杂音&#xff0c;那你可能已经感受到了 Android 音频硬件抽象层 (HAL) 出问题的后果&#xff01;在 Android 音频架构中&#xff0c…

51.WPF应用加图标指南 C#例子 WPF例子

完整步骤&#xff1a; 先使用文心一言生成一个图标如左边使用Windows图片编辑器编辑&#xff0c;去除背景使用正方形&#xff0c;放大图片使图标铺满图片使用格式工程转换为ico格式&#xff0c;分辨率为最大 在资源管理器中右键项目添加ico类型图片到项目里图片属性设置为始终…

运行fastGPT 第四步 配置ONE API 添加模型

上次已经装好了所有的依赖和程序。 下面在网页中配置One API &#xff0c;这个是大模型的接口。配置好了之后&#xff0c;就可以配置fastGPT了。 打开 OneAPI 页面 添加模型 这里要添加具体的付费模型的API接口填进来。 可以通过ip:3001访问OneAPI后台&#xff0c;**默认账号…

道旅科技借助云消息队列 Kafka 版加速旅游大数据创新发展

作者&#xff1a;寒空、横槊、娜米、公仪 道旅科技&#xff1a;科技驱动&#xff0c;引领全球旅游分销服务 道旅科技 &#xff08;https://www.didatravel.com/home&#xff09; 成立于 2012 年&#xff0c;总部位于中国深圳&#xff0c;是一家以科技驱动的全球酒店资源批发商…

51单片机——DS18B20温度传感器

由于DS18B20数字温度传感器是单总线接口&#xff0c;所以需要使用51单片机的一个IO口模拟单总线时序与DS18B20通信&#xff0c;将检测的环境温度读取出来 1、DS18B20模块电路 传感器接口的单总线管脚接至单片机P3.7IO口上 2、DS18B20介绍 2.1 DS18B20外观实物图 管脚1为GN…

Redis的安装和配置、基本命令

一、实验目的 本实验旨在帮助学生熟悉Redis的安装、配置和基本使用&#xff0c;包括启动Redis服务、使用命令行客户端进行操作、配置Redis、进行多数据库操作以及掌握键值相关和服务器相关的命令。 二、实验环境准备 1. JAVA环境准备&#xff1a;确保Java Development Kit …

2、ansible的playbook

ansible的脚本&#xff1a;playbook剧本 脚本的作用&#xff1a;复用 playbook的组成部分 1、开头 ---&#xff1a;表示是一个yaml文件&#xff0c;但是可以忽略。 2、Tasks&#xff08;任务&#xff09;&#xff1a;包含了目标主机上执行的操作&#xff0c;操作还是由模板来…

vscode的安装与使用

下载 地址&#xff1a;https://code.visualstudio.com/ 安装 修改安装路径&#xff08;不要有中文&#xff09; 点击下一步&#xff0c;创建桌面快捷方式&#xff0c;等待安装 安装中文插件 可以根据自己的需要安装python和Jupyter插件

Java : 各版本 jdk 下载及环境变量配置

--------------------------一、 JDK下载 ---------------------------- JDK下载地址&#xff1a;&#xff08;没有账号提示注册&#xff0c;最好用Chrome 浏览器&#xff09; Java Archive | Oracle 选择版本安装&#xff1a;&#xff08;注意不同系统&#xff09; 下载后按照…

IoTDB 查询时报可用内存不足

现象 IoTDB 3C3D 集群中&#xff0c;进行查询时报可用内存不足&#xff0c;即使是 show devices 这样简单的查询也会报内存不足。 原因 客户目前使用的 JDK 版本是 1.8, 该版本 JDK 对 GC 控制效果不佳&#xff0c;有可能出现可用内存不足的情况&#xff0c;同时 GC 耗时较长…

Jmeter 简单使用、生成测试报告(一)

一、下载Jmter 去官网下载&#xff0c;我下载的是apache-jmeter-5.6.3.zip&#xff0c;解压后就能用。 二、安装java环境 JMeter是基于Java开发的&#xff0c;运行JMeter需要Java环境。 1.下载JDK、安装Jdk 2.配置java环境变量 3.验证安装是否成功&#xff08;java -versio…

LabVIEW时域近场天线测试

随着通信技术的飞速发展&#xff0c;特别是在5G及未来通信技术中&#xff0c;天线性能的测试需求日益增加。对于短脉冲天线和宽带天线的时域特性测试&#xff0c;传统的频域测试方法已无法满足其需求。时域测试方法在这些应用中具有明显优势&#xff0c;可以提供更快速和精准的…

SSE 实践:用 Vue 和 Spring Boot 实现实时数据传输

前言 大家好&#xff0c;我是雪荷。最近我在灵犀 BI 项目中引入了 SSE 技术&#xff0c;以保证图表的实时渲染&#xff0c;当图表渲染完毕服务端推送消息至浏览器端触发重新渲染。 什么是 SSE&#xff1f; SSE 全称为 Server-Send Events 意思是服务端推送事件。 SSE 相比于 …