App下載

怎么通過Html5頁面播放M4a音頻文件?代碼詳解!

猿友 2021-07-30 11:47:28 瀏覽數(shù) (5421)
反饋

今天小編和大家分享有關(guān)于:“怎么通過Html5頁面播放M4a音頻文件?”這方面的相關(guān)內(nèi)容,下面是小編整理的相關(guān)內(nèi)容! 

業(yè)務(wù)場景:

手機app端錄音,然后上傳至后臺服務(wù)器,前端從后臺服務(wù)器獲取錄音,在PC端WEB頁面播放。

實際問題:

首先app錄音文件默認(rèn)是m4a格式,而在PC端WEB H5頁面,<audio>標(biāo)簽并沒有明確寫著支持m4a格式,如果app端生成的錄音不做相關(guān)設(shè)置,而用默認(rèn)設(shè)置,在H5上確實是播放不了的。

其實一開始,我沒有想太多,也是想著把m4a文件轉(zhuǎn)成mp3給前臺用。

在網(wǎng)上查了一番,很多都說用jave-1.0.2.2.jar,然而其實這個包很舊,而且在windows上是可以轉(zhuǎn),但centos8上不支m4a格式轉(zhuǎn)碼,在系統(tǒng)上有兼容性問題。信我,別用它。

然后又在碼庫里找了比較靠譜的是這個包,這里附個鏈接: https://github.com/a-schild/jave2,這個包也是基于ffmpeg的,提供了支持win64、osx64、linux64的依賴,建義在maven打包時,根據(jù)開發(fā)或生產(chǎn)環(huán)境的不同,打包時引用相應(yīng)環(huán)境的依賴。

下面附上我的m4a轉(zhuǎn)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>           
            <!--錄音轉(zhuǎn)換,jave-all-deps 包涵了所有平臺的依賴,由于打包太大,建議打包時選指定的依賴-->
            <!--<dependency>-->
                <!--<groupId>ws.schild</groupId>-->
                <!--<artifactId>jave-all-deps</artifactId>-->
                <!--<version>${jave.version}</version>-->
            <!--</dependency>-->
            <!--錄音轉(zhuǎn)換,指定平臺依賴,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配置,用來切換不同環(huán)境的配置-->
    <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>

錄音文件轉(zhuǎn)換代碼:

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 錄音轉(zhuǎn)換
 * @Author admin
 * @Version 1.0.0
 **/
@Component
public class AudioTransUtil {
    static {
    // 項目是springboot jar包, jar包內(nèi)的代碼要讀取外面文件夾的文件,需要處理一下讀取路徑,
    // 這里是把錄音源文件和轉(zhuǎn)換文件放在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 = "錄音轉(zhuǎn)換格式")
    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();
 
            //在有需要時添加,可根據(jù)不同系統(tǒng)環(huán)境,查看支持處理的文件格式
            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("錄音轉(zhuǎn)換路徑");
        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();
    }
 
    /**
     * 錄音轉(zhuǎn)碼處理監(jiān)聽器,可監(jiān)聽文件處理結(jié)果,對于錯誤信息很有用
     */
    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環(huán)境是可以正常轉(zhuǎn)換的,開一始,我的生產(chǎn)環(huán)境也用了這份。

后來,我去找了m4a和mp3、mp4的區(qū)別,發(fā)現(xiàn) mp4是使用了MPEG-4進(jìn)行封裝的AAC編碼,而M4A的本質(zhì)和音頻MP4相同,它是區(qū)別純音頻MP4文件和包含視頻的MP4文件而由蘋果(Apple)公司使用的擴展名。

那么疑問來了,竟然m4a和mp4的本質(zhì)相同,那么竟然瀏覽器H5可以播放mp4,為什么m4a不行,原因在音頻的編碼上,AAC編碼是解決問題的關(guān)鍵。

下面附上安卓內(nèi)部輸出錄音代碼中的幾個關(guān)鍵截圖:




默認(rèn)如果不設(shè)置,AudioEncoder是0,0并不是AAC編碼,我們需要在輸出格式上設(shè)置MPEG_4,并把編碼格式設(shè)置成AAC,

如第三圖中所示:

setOutPutFormat(MediaRecorder.OutputFormat.MPEG_4)

setAudioEncoder(MediaRecorder.AudioEncoder.AAC)

這樣,生成的m4a錄音文件,就可以直接在瀏覽器H5頁面中播放了,完全不需要后臺,在整個程序個不僅少了代碼的轉(zhuǎn)碼時間,本身m4a文件也很小。

以上就是有關(guān)于:“怎么通過Html5頁面播放M4a音頻文件?”這方面的相關(guān)問題,相信在閱讀完這篇文章后大家就有所了解了吧!當(dāng)然了在html5這方面的相關(guān)內(nèi)容不僅僅如此,更多有關(guān)于html5這方面的相關(guān)內(nèi)容都可以在W3Cschool中進(jìn)行學(xué)習(xí)和了解! 


0 人點贊