IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> java多媒体处理 -> 正文阅读

[游戏开发]java多媒体处理

方法一

<!--引入全平台windows 32/64 linux 32/64 下的ffmpeg 可执行程序,实际运行不需要这么多-->
        <!--<dependency>
            <groupId>ws.schild</groupId>
            <artifactId>jave-all-deps</artifactId>
            <version>3.2.0</version>
        </dependency>-->
        <!--操作ffmpeg命令的jar-->
        <dependency>
            <groupId>ws.schild</groupId>
            <artifactId>jave-core</artifactId>
            <version>3.2.0</version>
        </dependency>
        <!--linux 引用jar,主要集成 ffmpeg-amd64-3.1.1 linux下可执行文件  -->
        <dependency>
            <groupId>ws.schild</groupId>
            <artifactId>jave-nativebin-linux64</artifactId>
            <version>3.2.0</version>
        </dependency>
/**
     * 获取播放时长
     *
     * @param multipartFile 文件流
     */
    private int getPlayTime(MultipartFile multipartFile) {
        // 获取文件名
        String fileName = multipartFile.getOriginalFilename();
        // 播放时长
        int playTime = -1;
        File file = new File(fileName);
        try {
            FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
            MultimediaObject multimediaObject = new MultimediaObject(file);
            MultimediaInfo multimediaInfo = multimediaObject.getInfo();
            playTime = (int) multimediaInfo.getDuration() / 1000;
        } catch (Exception e) {
            BusinessExceptionUtil.throwErrorCodeException(ErrorCode.Status.UPLOAD_FILE_FAIL, e.toString());
            log.error("获取播放时长异常", e);
        } finally {
            file.delete();
        }
        return playTime;
    }

?

方法二

<!-- 视觉库 -->
        <!-- 总包太大,不需要这么多 -->
        <!-- <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.5.7</version>
        </dependency> -->
        <!-- javacv基础包 -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.5.7</version>
        </dependency>
        <!-- ffmpeg,根据javacv总包的版本 -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>ffmpeg-platform</artifactId>
            <version>5.0-1.5.7</version>
        </dependency>
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class ToolVideo {
    // 获取要取得的帧数
    private static final int GET_FRAMES_LENGTH = 6;

    /**
     * 测试
     *
     * @param args
     */
    public static void main(String[] args) throws FrameGrabber.Exception {
        File file = new File("D:\\Users\\外出乞讨\\Desktop\\测试用素材\\摩托.mp4");
        Map<String, Object> screenshot = getScreenshot(file);
    }

    /**
     * 视频:获取一张视频截图并保存同名的jpg文件到指定目录
     * 音频:获取播放时长
     *
     * @param file 文件
     * @return
     */
    public static Map<String, Object> getScreenshot(File file) {
        log.info("视频文件[{}]截图开始", file.getName());

        Map<String, Object> result = new HashMap<>();

        // 文件路径
        String filePath = file.getPath();
        // 视频文件名
        String fileName = file.getName();

        // 第一帧图片存储位置(也是视频路径)
        String targerFilePath = "";
        if (filePath.contains("\\")) {
            targerFilePath = filePath.substring(0, filePath.lastIndexOf("\\"));
            targerFilePath = targerFilePath + File.separator;
        } else if (filePath.contains("/")) {
            targerFilePath = filePath.substring(0, filePath.lastIndexOf("/"));
            targerFilePath = targerFilePath + File.separator;
        }

        // 图片名称
        String targetFileName = fileName.substring(0, fileName.lastIndexOf("."));
        // 图片的类型
        String imageMat = "jpg";
        // 图片的完整路径
        String imagePath = targerFilePath + targetFileName + "." + imageMat;

        // 创建文件
        File output = new File(imagePath);

        FFmpegFrameGrabber grabber;
        try {
            grabber = FFmpegFrameGrabber.createDefault(file);
            grabber.start();
            // 视频总帧数
            int videoLength = grabber.getLengthInFrames();

            Frame frame = null;
            int i = 0;
            while (i < videoLength) {
                // 过滤前5帧,避免出现全黑的图片,依自己情况而定(每循环一次取一帧)
                frame = grabber.grabFrame();
                if ((i > GET_FRAMES_LENGTH) && (frame.image != null)) {
                    break;
                }
                i++;
            }

            // 视频旋转度
            String rotate = grabber.getVideoMetadata("rotate");
            Java2DFrameConverter converter = new Java2DFrameConverter();
            // 绘制图片
            BufferedImage bi = converter.getBufferedImage(frame);
            if (rotate != null) {
                // 旋转图片
                bi = rotate(bi, Integer.parseInt(rotate));
            }

            // 输出图片
            ImageIO.write(bi, imageMat, output);

            // 拼接Map信息
            result.put("videoLength", videoLength); // 视频总帧数
            result.put("videoWide", bi.getWidth()); // 第一帧的宽
            result.put("videoHigh", bi.getHeight());// 第一帧的高
            long duration = grabber.getLengthInTime() / (1000 * 1000); // 此视频时长(s/秒)
            result.put("rotate", (null == rotate || "".equals(rotate)) ? "0" : rotate); // 视频的旋转度
            result.put("format", grabber.getFormat()); // 视频的格式
            result.put("imgPath", output.getPath());
            result.put("imgName", output.getName());
            result.put("duration", duration);

            log.info("视频文件[{}]截图结束,图片地址为[{}]", filePath, imagePath);

            grabber.close();
        } catch (Exception e) {
            log.error("视频信息帧数处理发生异常 [{}]", e.getMessage());
            e.printStackTrace();

            BusinessExceptionUtil.throwErrorCodeException(ErrorCode.Status.UPLOAD_FILE_FAIL, e.toString());
        }

        return result;
    }

    /**
     * file 转 btye[]
     *
     * @param file
     * @return
     */
    public static byte[] fileTobyte(File file) {
        byte[] buffer = null;
        try {
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }

    /**
     * 获取音频/视频时长
     * @param multipartFile 文件流
     * @return
     */
    public static int getPlayTime(MultipartFile multipartFile) {
        // 播放时长
        int playTime = -1;
        File file = null;
        FFmpegFrameGrabber grabberOne = null;
        try {
            // MultipartFile转file
            file = new File(multipartFile.getOriginalFilename());
            FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);

            // file转FFmpegFrameGrabber
            grabberOne = FFmpegFrameGrabber.createDefault(file);
            grabberOne.start();
            // 计算时长
            playTime = (int) grabberOne.getFormatContext().duration() / 1000000;
            grabberOne.stop();
        } catch (Exception e) {
            BusinessExceptionUtil.throwErrorCodeException(ErrorCode.Status.UPLOAD_FILE_FAIL, e.toString());
            log.error("获取播放时长异常", e);
        } finally {
            try{
                grabberOne.stop();
            }catch (Exception e) {
                BusinessExceptionUtil.throwErrorCodeException(ErrorCode.Status.UPLOAD_FILE_FAIL, e.toString());
                log.error("关闭流异常", e);
            }

            file.delete();
        }
        return playTime;
    }

    // ==================== private method ====================

    /**
     * <h5>功能:根据视频旋转度来调整图片</h5>
     *
     * @param src   捕获的图像
     * @param angel 视频旋转度
     * @return BufferedImage
     */
    private static BufferedImage rotate(BufferedImage src, int angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        int type = src.getColorModel().getTransparency();
        Rectangle rect_des = calcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);
        BufferedImage bi = new BufferedImage(rect_des.width, rect_des.height, type);
        Graphics2D g2 = bi.createGraphics();
        g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
        g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
        g2.drawImage(src, 0, 0, null);
        g2.dispose();
        return bi;
    }

    /**
     * <h5>功能:计算图片旋转大小</h5>
     *
     * @param src   屏幕坐标中捕获的矩形区域
     * @param angel 视频旋转度
     * @return
     */
    private static Rectangle calcRotatedSize(Rectangle src, int angel) {
        if (angel >= 90) {
            if (angel / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel = angel % 90;
        }
        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angel_dalta_width = Math.atan((double) src.height / src.width);
        double angel_dalta_height = Math.atan((double) src.width / src.height);
        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        return new Rectangle(new Dimension(des_width, des_height));
    }
}

?

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 16:21:40  更:2022-04-06 16:23:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 20:10:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码