引言

前段时间有个项目需求,需要对一段完整的音频按照开始时间和结束时间进行截取。网上查了一些相关资料,最后采用JAVE Java类库实现。

介绍

JAVE (Java Audio Video Encoder) 类库是一个 ffmpeg 项目的 Java 语言封装。开发人员可以使用JAVE 在不同的格式间转换视频和音频,实现视频和音频文件的截取功能。

思路

1. 如果是直接截取本地文件,代码很简单,直接引入jave jar包,实现截取功能即可。
2. 对于不是本地文件,而是一个远程文件的链接情况,就需要先下载文件到指定路径,再进行截取,最后将截取后的路径更新到对应记录,便可以拿到一个直接可下载的链接。在项目中,使用的是oss进行文件管理,所以又涉及到一些oss的使用。

实现及核心代码

1. 下载jar包,并上传到maven仓库

jave jar包下载地址
参考博客:jar上传Maven私服

2. 实现音频截取代码

将jar上传到私服后,就可以直接在maven项目中引入依赖,下面是截取音频代码:
package com.quyixian.word.book.back.utils;import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.MultimediaInfo;
import lombok.extern.slf4j.Slf4j;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;/*** 截取音频文件工具类*/
@Slf4j
public class ReadVideoUtil {/*** 截取mp3音频文件** @param sourceFile 源文件地址* @param targetFile 目标文件地址* @param start      截取开始时间(秒)* @param end        截取结束时间(秒)*                   <p>*                   return  截取成功返回true,否则返回false*/public static boolean cut(String sourceFile, String targetFile, int start, int end) {try {if (!sourceFile.toLowerCase().endsWith(".mp3") || !targetFile.toLowerCase().endsWith(".mp3")) {return false;}File wav = new File(sourceFile);if (!wav.exists()) {return false;}//总时长(秒)long t1 = getTimeLen(wav);if (start < 0 || end <= 0 || end > t1 || start >= end) {return false;}FileInputStream fis = new FileInputStream(wav);//音频数据大小(44为128kbps比特率wav文件头长度)long wavSize = wav.length() - 44;//截取的音频数据大小long splitSize = (wavSize / t1) * (end - start);//截取时跳过的音频数据大小long skipSize = (wavSize / t1) * start;int splitSizeInt = Integer.parseInt(String.valueOf(splitSize));int skipSizeInt = Integer.parseInt(String.valueOf(skipSize));//存放文件大小,4代表一个int占用字节数ByteBuffer buf1 = ByteBuffer.allocate(4);//放入文件长度信息buf1.putInt(splitSizeInt + 36);//代表文件长度byte[] flen = buf1.array();//存放音频数据大小,4代表一个int占用字节数ByteBuffer buf2 = ByteBuffer.allocate(4);//放入数据长度信息buf2.putInt(splitSizeInt);//代表数据长度byte[] dlen = buf2.array();//数组反转flen = reverse(flen);dlen = reverse(dlen);//定义wav头部信息数组byte[] head = new byte[44];//读取源wav文件头部信息fis.read(head, 0, head.length);//4代表一个int占用字节数for (int i = 0; i < 4; i++) {//替换原头部信息里的文件长度head[i + 4] = flen[i];//替换原头部信息里的数据长度head[i + 40] = dlen[i];}//存放截取的音频数据byte[] fbyte = new byte[splitSizeInt + head.length];//放入修改后的头部信息for (int i = 0; i < head.length; i++) {fbyte[i] = head[i];}//存放截取时跳过的音频数据byte[] skipBytes = new byte[skipSizeInt];//跳过不需要截取的数据fis.read(skipBytes, 0, skipBytes.length);//读取要截取的数据到目标数组fis.read(fbyte, head.length, fbyte.length - head.length);fis.close();File target = new File(targetFile);//如果目标文件已存在,则删除目标文件if (target.exists()) {target.delete();}FileOutputStream fos = new FileOutputStream(target);fos.write(fbyte);fos.flush();fos.close();} catch (IOException e) {log.error("[ReadVideoUtil.cut] [error] [sourceFile is {}, targetFile is{}, start time is {}, end time is {}]", sourceFile, targetFile, start, end, e);return false;}return true;}/*** 获取音频文件总时长** @param filePath* @return*/public static long getTimeLen(File filePath) {long tlen = 0;if (filePath != null && filePath.exists()) {Encoder encoder = new Encoder();try {MultimediaInfo m = encoder.getInfo(filePath);long ls = m.getDuration();tlen = ls / 1000;} catch (Exception e) {log.error("[ReadVideoUtil.getTimeLen] [error] [param is {}]", filePath, e);}}return tlen;}/*** 数组反转** @param array*/public static byte[] reverse(byte[] array) {byte temp;int len = array.length;for (int i = 0; i < len / 2; i++) {temp = array[i];array[i] = array[len - 1 - i];array[len - 1 - i] = temp;}return array;}/*** 使用本地文件测试截取效果** @param args*/public static void main(String[] args) {System.out.println(cut("E:\\7a0f34cb-e9e2-4863-b267-140d3f915929.mp3", "E:\\7a0f34cb-e9e2-4863-b267-140d3f915929-cut_8_30.mp3", 8, 30));}}
因为提供给我们的音频文件格式是mp3,所以上面代码检查了文件是否是mp3,其他格式的音频如wav也是可以实现功能的。
以上代码来源博客:Java切割音频文件

3. 根据URL下载文件到指定路径

/*** 文件下载** @param audioPath* @param savePath  文件地址 示例:D:/ceshi/1.png* @throws Exception*/
public static void downloadFile(String audioPath, String savePath) throws Exception {DataInputStream in = null;DataOutputStream out = null;try {File file = new File(savePath);if (!file.exists()) {//判断文件是否存在,不存在则创建文件file.createNewFile();}URL url = new URL(audioPath);HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();urlCon.setConnectTimeout(6000);urlCon.setReadTimeout(6000);int code = urlCon.getResponseCode();if (code != HttpURLConnection.HTTP_OK) {throw new Exception("文件读取失败");}in = new DataInputStream(urlCon.getInputStream());out = new DataOutputStream(new FileOutputStream(savePath));byte[] buffer = new byte[2048];int count = 0;while ((count = in.read(buffer)) > 0) {out.write(buffer, 0, count);}} catch (Exception e) {log.error("save file", e);} finally {if (out != null) {out.close();}if (in != null) {in.close();}}
}

4. 上传至阿里云OSS

(1)引入aliyun-oss-sdk
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>2.8.3</version>
</dependency>
(2)配置密钥等信息
oss:access-key-id: ******access-key-secret: ******end-point: ******bucket-name: ******
(3)上传文件至OSS
@Resource
private OssConfig ossConfig;private OSSClient ossClient;/*** 上传文件** @param url     源文件路径* @param fileDir 上传到OSS的位置* @return*/
public String upload(String url, String fileDir) {try {File file = new File(url);FileInputStream fileInputStream = new FileInputStream(file);String[] split = url.split("/");String result = this.uploadFileOSS(fileInputStream, split[split.length - 1], fileDir);if (!StringUtil.isEmpty(result)) {// 上传oss成功之后删除临时文件file.delete();return result;}} catch (FileNotFoundException e) {e.printStackTrace();log.error("上传文件失败");}return "";
}/*** 上传到OSS服务器 如果同名文件会覆盖** @param inputStream 文件流* @param fileName    文件名称 包括后缀名* @return 出错返回"" ,唯一MD5数字签名*/
public String uploadFileOSS(InputStream inputStream, String fileName, String fileDir) {long currentTime = System.currentTimeMillis();String ret = "";try {ossClient = new OSSClient(ossConfig.getEndPoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());// 创建上传Object的MetadataObjectMetadata objectMetadata = new ObjectMetadata();objectMetadata.setContentLength(inputStream.available());objectMetadata.setCacheControl("no-cache");objectMetadata.setHeader("Pragma", "no-cache");objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));objectMetadata.setContentDisposition("inline;filename=" + fileName);log.info("开始上传文件...");PutObjectResult putResult = ossClient.putObject(ossConfig.getBucketName(), fileDir + fileName, inputStream, objectMetadata);if (StringUtils.isNotBlank(putResult.getETag())) {ret = fileDir + fileName;}log.info("文件上传完成,耗时:{}ms", System.currentTimeMillis() - currentTime);} catch (IOException e) {log.error("上传文件到OSS时出现未知异常:" + e);} finally {try {if (inputStream != null) {inputStream.close();}} catch (IOException e) {log.error("上传文件到OSS后,关闭IO流时出现未知异常:" + e);}}return ret;
}/*** Description: 判断OSS服务文件上传时文件的contentType* <p>* 文件后缀** @return String*/
public static String getcontentType(String filenameExtension) {if (filenameExtension.equalsIgnoreCase("bmp")) {return "image/bmp";}if (filenameExtension.equalsIgnoreCase("gif")) {return "image/gif";}if (filenameExtension.equalsIgnoreCase("jpeg") || filenameExtension.equalsIgnoreCase("jpg")|| filenameExtension.equalsIgnoreCase("png")) {return "image/jpeg";}if (filenameExtension.equalsIgnoreCase("html")) {return "text/html";}if (filenameExtension.equalsIgnoreCase("txt")) {return "text/plain";}if (filenameExtension.equalsIgnoreCase("vsd")) {return "application/vnd.visio";}if (filenameExtension.equalsIgnoreCase("pptx") || filenameExtension.equalsIgnoreCase("ppt")) {return "application/vnd.ms-powerpoint";}if (filenameExtension.equalsIgnoreCase("docx") || filenameExtension.equalsIgnoreCase("doc")) {return "application/msword";}if (filenameExtension.equalsIgnoreCase("pdf")) {return "application/pdf";}if (filenameExtension.equalsIgnoreCase("xml")) {return "text/xml";}if (filenameExtension.equalsIgnoreCase(".mp3")) {return "audio/mp3";}if (filenameExtension.toLowerCase().endsWith("mp4")) {return "video/mpeg4";}if (filenameExtension.toLowerCase().endsWith("wav")) {return "audio/wav";}return "image/jpeg";
}

总结

遇到这种没有接触过的需求,首先要做的是通过查询资料确定实现方案。确定方案之后可以先自己实现demo,再结合项目实际场景,完成需求就很容易了。

JAVE实现音频截取并上传OSS相关推荐

  1. PHP版微信权限验证配置,音频文件下载,FFmpeg转码,上传OSS和删除转存服务器本地文件...

    2019独角兽企业重金招聘Python工程师标准>>> 一.概述和通过config接口注入权限验证配置 由于微信的临时素材(如:录音文件)上传到微信服务器上,微信后台保存时间为3天. ...

  2. 通过url链接将图片上传oss图片显示不完整问题

    通过url链接将图片上传oss图片显示不完整问题 问题:在之前通过链接上传图片的时候,都是先获取inputStream流,然后通过available()方法获取文件大小.但是通过这种方法获取到的文件大 ...

  3. uedit php,laravel uedit上传oss

    laravel ueditor上传oss 首先下载ueditor包安装好! ueditor包没有?好吧,看这里laravel ueditor教程 oss包没有?好吧,看这里laravel oss教程 ...

  4. SpringBoot 二维码生成base64并上传OSS

    SpringBoot 二维码生成base64并上传OSS 基础环境 SpringBoot.Maven 代码实现 1.添加依赖 <!--二维码生成 --> <dependency> ...

  5. 文件(图片,音频)上传OSS并返回上传地址

    为了加快速度这里用多线程 package cn.oss.test;import java.io.InputStream; import java.util.concurrent.Callable; i ...

  6. springboot 通过javaCV 实现mp4转m3u8 上传oss

    配置依赖 <properties><java.version>11</java.version><ffmpeg.version>0.6.2</ff ...

  7. 文件上传oss服务器

    最近接到个需求,项目文件由原来上传至服务器本地改为上传至阿里oss服务器中.查看了官方相关文档后最终成功实现,在此记录一下相关经验. 官网文档:https://help.aliyun.com/docu ...

  8. Python:自动化上传OSS

    简介 最近在学习Python,为之庞大的第三方库感到震撼.今天分享一个Python 自动化脚本,功能是将H5静态资源上传到OSS,以方便实现CDN加速,我将其放在Jenkins自动发布中使用.该脚本不 ...

  9. PPTPDF文件转换成图片上传OSS

    PPTPDFIMAGE 先把文件上传至本地,再去读取文件转变上传. <dependency><groupId>org.apache.pdfbox</groupId> ...

  10. 文件传服务器上全是乱码,解决txt文件上传oss服务器乱码的问题

    今天上传txt文件下载下来却乱码,搞了一下午,发现还挺复杂.记录一下. 1.首先服务器只接受utf-8格式的文件,所以首先想到的就是转码问题. 这是网上很容易就找到的判断文件编码的代码.判断出来之后如 ...

最新文章

  1. 【全网首发】京东AI三大NLP项目实战
  2. Iso时间转java instant,在java.util.Date和java.time.Instant之间转换古代日期时的差异
  3. MSSQL 2005 DML触发器
  4. PhoneGap与Jquery Mobile结合开发android应用配置
  5. SpringBoot_入门-微服务简介
  6. [转载]Mac使用vim命令修改配置文件内容
  7. c ++查找字符串_C ++异常处理| 查找输出程序| 套装1
  8. php把数据创建一个表格,PHP创建(导出Excel数据表格)
  9. 2.5 指数加权平均的偏差修正
  10. ios开发--企业帐号发布
  11. malformed utf-8 characters, possibly incorrectly encoded
  12. 容器技术20年:容器引擎与江湖门派
  13. http(S)系列之(五):android之HttpURLConnection源码解析(1)
  14. 在北京税前工资2万元,扣掉社保五险和一金税后能拿多少钱?
  15. Oliver的救援(bfs)
  16. 从零开始搭建Java环境
  17. SQL语句group by 的求和sum
  18. OpenCASCADE 获取面中心点法向
  19. VRP基础(华为设备操作系统)
  20. 国际版抖音Tik Tok怎么引流变现,卖家所不知道的那些事

热门文章

  1. E-prime 鼠标点击选择
  2. linux自动ping脚本,linux 自动ping ip的shell脚本
  3. 计算机自动生成凭证,哪些财务软件能自动生成记账凭证?
  4. 疑难杂症 | Win10解压文件后乱码
  5. vs 2017 配置 boost 库
  6. windows系统下帧率获取工具--fraps
  7. Jdk(1.6和1.8)中英文Api文档
  8. 黄山旅游自助攻略住宿行程路线篇
  9. redis/memcache监控管理工具——treeNMS
  10. 因使用盗版软件赔偿 869 万元 :CIO被开除、罚 15 万元