代码之家  ›  专栏  ›  技术社区  ›  ken

如何从录音机流式传输音频并同时保存为音频文件?

  •  0
  • ken  · 技术社区  · 5 年前

    当audioRecorder正在使用OkHttp录制时,我想将音频流传输到我的服务器。同时,我想录制的音频成为一个音频文件在本地安卓设备。

    以下是我尝试的:

    private void startRecordAudio() {
            audioRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE, CHANNEL,AUDIO_FORMAT, BUFFER_SIZE);
            audioRecorder.startRecording();
            recordingProgress.set(true);
            recordingThread = new Thread(new StreamRecordingRunnable(), "Stream Recording");
            recordingThread.start();
    }
    

    然后在 StreamRecordingRunnable() 我喜欢这样:

    private class StreamRecordingRunnable implements  Runnable{
    
            @Override
            public void run() {
                final ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
    
                RequestBody requestBody = new RequestBody() {
                    @Nullable
                    @Override
                    public MediaType contentType() {
                        return MediaType.parse("audio/raw;encoding=signed-integer;bits=16;rate=8000;endian=little;");
                    }
    
                    @Override
                    public void writeTo(@NonNull BufferedSink sink) throws IOException {
                        while(recordingProgress.get()){
                            int result = audioRecorder.read(buffer, BUFFER_SIZE);
    
                            if(result < 0){
                                Log.d(LOG_TAG, " Some streaming error here");
    
                            }else{
                                Log.d(LOG_TAG, " No problem here");
                                writeAudioDataToFile(); // Here I want to save the audio file before it send to server.
                                sink.write(buffer);
                                buffer.clear();
                            }
    
                        }
                    }
                };
            
    
                Request request = httpRequestBuilder.post(requestBody).build();
                try(Response response = httpClient.newCall(request).execute()){
                    if(response.isSuccessful()){
                        Log.v("OKHTTP", response.body().string());
                    }else{
                        Log.d("http not successful", String.valueOf(response.body()));
                    }
    
                }catch (IOException e){
                    Log.d("HTTP", e.getMessage());
                }
    
    
            }
        }
    

    完成以上所有代码后,我可以在录音机开始录音时发送音频文件。我可以在我的服务器中获取音频文件。

    我现在想做的是:

    制造 writeAudioDataToFile() 功能,我希望它存储的音频(将发送到服务器),到一个本地的Android设备内的本地文件。

    这就是我想要的 writeAudioDataToFile() ,应存储在名为 audiotest12345.wav

        int BufferElements2Rec = 1024; // want to play 2048 (2K) since 2 bytes we use only 1024
        int BytesPerElement = 2;
        String filePath;
    
        private void writeAudioDataToFile() {
            // Write the output audio in byte
    
            filePath = getExternalCacheDir().getAbsolutePath();
            filePath += "/audiorecordtest12345.wav";
    
            short sData[] = new short[BufferElements2Rec];
    
            FileOutputStream os = null;
            try {
                os = new FileOutputStream(filePath);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
    
            while (recordingProgress.get()) {
                // gets the voice output from microphone to byte format
    
                audioRecorder.read(sData, 0, BufferElements2Rec);
                System.out.println("Short wirting to file" + sData.toString());
                try {
                    // // writes the data to file from buffer
                    // // stores the voice buffer
                    byte bData[] = short2byte(sData);
                    os.write(bData, 0, BufferElements2Rec * BytesPerElement);
    
                    Log.d("file name", filePath);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private byte[] short2byte(short[] sData) {
            int shortArrsize = sData.length;
            byte[] bytes = new byte[shortArrsize * 2];
            for (int i = 0; i < shortArrsize; i++) {
                bytes[i * 2] = (byte) (sData[i] & 0x00FF);
                bytes[(i * 2) + 1] = (byte) (sData[i] >> 8);
                sData[i] = 0;
            }
            return bytes;
    
        } 
    

    结果:

    但这样做,它不仅没有保存一个文件在本地,它也无法发送到服务器。我也试过这个:

    private class StreamRecordingRunnable implements  Runnable{
    
            @Override
            public void run() {
                writeAudioDataToFile();
                final ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
    
                //..all the RequestBody and networking call same as above
            }
    }
    

    如果我只做一个操作,意味着只保存文件或只发送到服务器,代码是工作的。但当我同时做的时候,它就不起作用了。

    音频测试12345.wav adb shell

    这应该是因为1个麦克风中只有1个可能设备。但是我不知道我需要做什么才能同时完成这两项手术

    因此,我的问题是:

    1. 如何从录音机中保存音频文件并同时发送到服务器?

    2. BufferedSink 价值?但我不知道怎么做,因为我是新来的 缓冲接收器 关于大雄,我不太明白这是怎么回事。

    3. 因此,如果可能,请解释 也用于

    0 回复  |  直到 5 年前
    推荐文章