天天看點

Android 音視訊配音之音頻提取、截斷、混音、合并、合成(二)——将提取的PCM根據時間戳截斷

前言

  1. 通過上篇文章我們知道了如何從MP4視訊中如何提取出PCM或者WAV,那麼這篇文章則是如何截斷PCM音頻
  2. 該文章系列是視訊配音,涉及到把背景音頻從視訊中提取出來、背景音頻根據台詞時間戳進行截斷、截斷的背景和錄音混合、混合音頻進行拼接合并、合并後的音頻轉碼為m4a格式、将m4a格式音頻和視訊合并生成mp4視訊檔案
  3. 使用的視訊格式:MP4     音頻格式以及編碼:m4a(aac)    采樣率:44100   聲道:雙聲道  采樣位數:16
  4. 文章使用的測試音頻為http網絡視訊,如果不是在視訊丢失的情況下無法讀取,請閱讀一下該文章:Http網絡請求無響應解決辦法
  5. 上篇文章:Android 音視訊配音之音頻提取、截斷、混音、合并、合成(一)——從視訊中提取音頻檔案

截斷前的準備

  • 了解pcm音頻的屬性

          pcm主要有聲道數、采樣率、采樣大小這幾個關鍵屬性參數,而我們可以通過這幾個參數,進行換算,得到pcm的碼率,進而換算出音頻長度,進而可以根據所要截取的音頻時間進行相應截斷

  • 截取公式

         每秒資料量=采樣率∗聲倒數∗bitnum/1000/8

        得到每秒資料量之後我們就可以得到截取時間區間的開始資料量和結束資料量,進而截取到相應片段,即:

       開始時間索引=每秒采樣率*開始時間

      結束時間索引=每秒采樣率*結束時間

     截取的音頻片段資料=總音頻資料[結束時間索引]-總音頻資料[開始時間索引]

開始截斷

通過上面的公式和從視訊中提取音頻檔案我們就可以知道,隻需要知道音頻每一句的開始時間和結束時間,那麼代碼如下

byte[] bytes=byteArrayOutputStream.toByteArray();//讀取整個音頻的資料
        byteArrayOutputStream.close();
        if (bytes.length==0){
            if (handler!=null){
                handler.sendEmptyMessage(0);
            }
            return;
        }
        for (int i=0;i<times.length-1;i++){
            long startTime=times[i];
            long endTime=times[i+1];
            //擷取資料開始資料索引
            int startPosition=getPositionFromWave(startTime,KEY_SAMPLE_RATE,KEY_CHANNEL_COUNT,bitNumber);
            //擷取資料結束資料索引
            int endPosition=endTime==-1?bytes.length-1:getPositionFromWave(endTime,KEY_SAMPLE_RATE,KEY_CHANNEL_COUNT,bitNumber);
            if (endPosition>bytes.length-1){
                endPosition=bytes.length-1;
            }
            if (startPosition==endPosition-1||startPosition>=endPosition){
                break;
            }
            byte[]  cutBytes;//= Arrays.copyOfRange(bytes,startPosition,endPosition+1);
            if (KEY_CHANNEL_COUNT==1){//如果是單通道需要轉為雙通道
                cutBytes= byteMerger(Arrays.copyOfRange(bytes,startPosition,endPosition+1));
            }else{
                cutBytes= Arrays.copyOfRange(bytes,startPosition,endPosition+1);
            }
            File cutFile=new File(dirPath,audioName+"_"+i+suffixName);
            if (!cutFile.exists()){
                cutFile.createNewFile();
                FileOutputStream cutFileOutputStream=new FileOutputStream(cutFile);
                if (isWav){
                    convertPcmToWav(cutFileOutputStream,cutBytes,KEY_SAMPLE_RATE,KEY_CHANNEL_COUNT,bitNumber);
                }else{
                    cutFileOutputStream.write(cutBytes);
                    cutFileOutputStream.close();
                }
            }
        }
           

timeis的資料,這個資料是提取出來的音頻時間戳得到的,是以隻适合我的測試資料。你們的資料需要根據你們的方法提煉需要截取的時間段

private static final long[] times={0,1060,2620,4240,8680,9860,11520,13920,17530,19150,20510,22020,25330,27770,30030,33110,34950,39730,43570,-1};
           

Demo下載下傳

github

csdn