业务场景:
手机app端录音,然后上传至后台服务器,前端从后台服务器获取录音,在pc端web页面播放。
实际问题:
首先app录音文件默认是m4a格式,而在pc端web h5页面,<audio>标签并没有明确写着支持m4a格式,如果app端生成的录音不做相关设置,而用默认设置,在h5上确实是播放不了的。
其实一开始,我没有想太多,也是想着把m4a文件转成mp3给前台用。
在网上查了一番,很多都说用jave-1.0.2.2.jar,然而其实这个包很旧,而且在windows上是可以转,但centos8上不支m4a格式转码,在系统上有兼容性问题。信我,别用它。
然后又在码库里找了比较靠谱的是这个包,这里附个链接: https://github.com/a-schild/jave2,这个包也是基于ffmpeg的,提供了支持win64、osx64、linux64的依赖,建义在maven打包时,根据开发或生产环境的不同,打包时引用相应环境的依赖。
下面附上我的m4a转mp3的java代码:
pom.xml
<?xml version="1.0" encoding="utf-8"?> <project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelversion>4.0.0</modelversion> <groupid>com</groupid> <artifactid>test</artifactid> <version>1.0.0-snapshot</version> <packaging>pom</packaging> <properties> <jave.version>2.7.1</jave.version> </properties> <dependencymanagement> <dependencies> <!--录音转换,jave-all-deps 包涵了所有平台的依赖,由于打包太大,建议打包时选指定的依赖--> <!--<dependency>--> <!--<groupid>ws.schild</groupid>--> <!--<artifactid>jave-all-deps</artifactid>--> <!--<version>${jave.version}</version>--> <!--</dependency>--> <!--录音转换,指定平台依赖,jave-core必需指定--> <dependency> <groupid>it.sauronsoftware</groupid> <artifactid>jave</artifactid> <groupid>ws.schild</groupid> <artifactid>jave-core</artifactid> <version>${jave.version}</version> </dependency> </dependencies> </dependencymanagement> <!--激活profile配置,用来切换不同环境的配置--> <profiles> <profile> <id>dev</id> <properties> <profiles.actives>dev</profiles.actives> </properties> <activation> <activebydefault>true</activebydefault> <activebydefault>false</activebydefault> </activation> <dependencies> <dependency> <groupid>ws.schild</groupid> <artifactid>jave-nativebin-linux64</artifactid> <version>${jave.version}</version> </dependency> </dependencies> </profile> <profile> <id>pro</id> <properties> <profiles.actives>pro</profiles.actives> </properties> <activation> <activebydefault>false</activebydefault> </activation> <dependencies> <dependency> <groupid>ws.schild</groupid> <artifactid>jave-nativebin-linux64</artifactid> <version>${jave.version}</version> </dependency> </dependencies> </profile> <profile> <id>test</id> <properties> <profiles.actives>test</profiles.actives> </properties> <activation> <activebydefault>true</activebydefault> </activation> <dependencies> <dependency> <groupid>ws.schild</groupid> <artifactid>jave-nativebin-win64</artifactid> <version>${jave.version}</version> </dependency> </dependencies> </profile> </profiles> </project>
录音文件转换代码:
package com.utils; import com.alibaba.fastjson.json; import com.qirui.framework.common.base.syslog.syslog; import com.qirui.framework.common.base.syslog.syslogannotation; import com.qirui.framework.common.base.syslog.syslogprint; import com.qirui.framework.common.utils.requestutil; import org.springframework.stereotype.component; import ws.schild.jave.*; import java.io.bufferedoutputstream; import java.io.file; import java.io.fileoutputstream; import java.io.ioexception; /** * @classname audiotransutil * @description 录音转换 * @author admin * @version 1.0.0 **/ @component public class audiotransutil { static { // 项目是springboot jar包, jar包内的代码要读取外面文件夹的文件,需要处理一下读取路径, // 这里是把录音源文件和转换文件放在springboot jar包的同级文件夹下 string path = audiotransutil.class.getprotectiondomain().getcodesource().getlocation().getpath(); if(path.contains("jar")){ //file:/f:/ideaworkspace/test/smp-admin/framework-client/target/framework-client-0.0.1-snapshot.jar!/boot-inf/lib/framework-service-0.0.1-snapshot.jar!/ //去掉 "file:" path = path.substring(path.indexof("/"), path.length()); } if(system.getproperty("os.name").contains("dows")) { path = path.substring(1, path.length()); //widonws的jar包 if(path.contains("jar")){ path = path.substring(0, path.indexof(".jar")); rootpath = path.substring(0, path.lastindexof("/")); }else{ rootpath = path.replace("/target/classes/", ""); } }else if(system.getproperty("os.name").contains("mac")){ rootpath = path.replace("/target/classes/", ""); } else { path = path.substring(0, path.indexof(".jar")); rootpath = path.substring(0, path.lastindexof("/")); } } protected static final string rootpath; /** *目录路径 */ private static final stringbuilder dirpathstr = new stringbuilder(rootpath).append("/temp/audio/"); private static final string mp3 = "mp3"; @syslogannotation(descript = "录音转换格式") public string trans2mp3(byte[] sourceaudiobytes, string sourceaudioname){ //文件路径 string soureaudiofilepathstr = new stringbuilder(dirpathstr).append(sourceaudioname).tostring(); string sourceaudiotype = sourceaudioname.substring(sourceaudioname.indexof(".")+1); string targetaudiofilepathstr = new stringbuilder(soureaudiofilepathstr).tostring().replace(sourceaudiotype, mp3); bufferedoutputstream bos = null; fileoutputstream fos = null; try{ file dir = new file(dirpathstr.tostring()); if(!dir.exists()){ dir.mkdirs(); } file sourceaudiofile = new file(soureaudiofilepathstr); fos = new fileoutputstream(sourceaudiofile); bos = new bufferedoutputstream(fos); bos.write(sourceaudiobytes); file targetaudiofile = new file(targetaudiofilepathstr); audioattributes audioattributes = new audioattributes(); audioattributes.setcodec("libmp3lame"); audioattributes.setbitrate(new integer(32000)); // audioattributes.setchannels(new integer(2)); // audioattributes.setsamplingrate(new integer(22050)); encodingattributes attrs = new encodingattributes(); attrs.setformat("mp3"); attrs.setaudioattributes(audioattributes); encoder encoder = new encoder(); //在有需要时添加,可根据不同系统环境,查看支持处理的文件格式 system.out.println("encoder.getvideodecoders():" + json.tojson(encoder.getvideodecoders()).tostring()); system.out.println("encoder.getsupporteddecodingformats():" + json.tojson(encoder.getsupporteddecodingformats()).tostring()); myjavelistener myjavelistener = new myjavelistener(); encoder.encode(new multimediaobject(sourceaudiofile), targetaudiofile, attrs, myjavelistener); }catch (exception e){ e.printstacktrace(); }finally { try { if(null != bos){ bos.close(); } if(null != fos){ fos.close(); } } catch (ioexception e) { e.printstacktrace(); } } syslog syslog = new syslog(); syslog.setlogid(requestutil.getaccesslogid()); syslog.setparams(targetaudiofilepathstr); syslog.setdescript("录音转换路径"); syslogprint.printsyslogbody(syslog); return targetaudiofilepathstr; } // 删除本地临时录音 public void deletetempaudio(string filename){ //文件路径 string filenametemp = filename.substring(filename.lastindexof("/")+1, filename.length()); string soureaudiofilepathstr = new stringbuilder(dirpathstr).append(filenametemp).tostring(); string sourceaudiotype = filename.substring(filename.indexof(".")+1); string targetaudiofilepathstr = new stringbuilder(soureaudiofilepathstr).tostring().replace(sourceaudiotype, mp3); file file = new file(soureaudiofilepathstr); file.delete(); file = new file(targetaudiofilepathstr); file.delete(); } /** * 录音转码处理监听器,可监听文件处理结果,对于错误信息很有用 */ private class myjavelistener implements encoderprogresslistener { @override public void sourceinfo(multimediainfo multimediainfo) { system.out.println("mylistener.sourceinfo:" + json.tojson(multimediainfo).tostring()); } @override public void progress(int i) { system.out.println("mylistener.progress:" + i); } @override public void message(string s) { system.out.println("mylistener.message:" + s); } } }
上面的代码,在centos8环境是可以正常转换的,开一始,我的生产环境也用了这份。
后来,我去找了m4a和mp3、mp4的区别,发现 mp4是使用了mpeg-4进行封装的aac编码,而m4a的本质和音频mp4相同,它是区别纯音频mp4文件和包含视频的mp4文件而由苹果(apple)公司使用的扩展名。
那么疑问来了,竟然m4a和mp4的本质相同,那么竟然浏览器h5可以播放mp4,为什么m4a不行,原因在音频的编码上,aac编码是解决问题的关键。
下面附上安卓内部输出录音代码中的几个关键截图:
默认如果不设置,audioencoder是0,0并不是aac编码,我们需要在输出格式上设置mpeg_4,并把编码格式设置成aac,
如第三图中所示:
setoutputformat(mediarecorder.outputformat.mpeg_4) setaudioencoder(mediarecorder.audioencoder.aac)
这样,生成的m4a录音文件,就可以直接在浏览器h5页面中播放了,完全不需要后台,在整个程序个不仅少了代码的转码时间,本身m4a文件也很小。
到此这篇关于html5页面播放m4a音频文件的文章就介绍到这了,更多相关html5播放m4a 内容请搜索代码网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持代码网!
发表评论