25

データストレージをアプリではなくアプリで処理して、音声を録音する例を見つけようとしていMediaRecorderます。ユースケースには、記録を内部ストレージに保存することや、記録を暗号化することが含まれます。

createPipe()原則として、これはonによって作成されたパイプを使用して機能するはずParcelFileDescriptorですが、出力が正しくありません。

まず、これは、を使用して「自然に」記録し、外部ストレージの出力ファイルに直接書き込むサンプルプロジェクトです。このアプリは問題なく動作し、出力は、記録されたAndroidデバイスまたはLinuxボックスのVLCのいずれかで再生できます。MediaRecorderMediaRecorder

これがこのプロジェクトの私のcreatePipe()バリエーションですMediaRecorder一般的な構成(例)の観点からはsetOutputFormat()、最初の構成と同じであるため、コードはおそらく正しいと思われます。

ただし、次の方法で出力を提供しています。

  recorder.setOutputFile(getStreamFd());

getStreamFd()を使用createPipe()すると、パイプから読み取るためのバックグラウンドスレッドが生成され、次のユーザーが使用できるように書き込み終了が返されますMediaRecorder

  private FileDescriptor getStreamFd() {
    ParcelFileDescriptor[] pipe=null;

    try {
      pipe=ParcelFileDescriptor.createPipe();

      new TransferThread(new AutoCloseInputStream(pipe[0]),
                       new FileOutputStream(getOutputFile())).start();
    }
    catch (IOException e) {
      Log.e(getClass().getSimpleName(), "Exception opening pipe", e);
    }

    return(pipe[1].getFileDescriptor());
  }

TransferThreadは古典的なjava.ioストリーム間コピールーチンであり、出力ファイルをフラッシュおよび同期するためのスマート機能が追加されています。

  static class TransferThread extends Thread {
    InputStream in;
    FileOutputStream out;

    TransferThread(InputStream in, FileOutputStream out) {
      this.in=in;
      this.out=out;
    }

    @Override
    public void run() {
      byte[] buf=new byte[8192];
      int len;

      try {
        while ((len=in.read(buf)) > 0) {
          out.write(buf, 0, len);
        }

        in.close();

        out.flush();
        out.getFD().sync();
        out.close();
      }
      catch (IOException e) {
        Log.e(getClass().getSimpleName(),
              "Exception transferring file", e);
      }
    }
  }

2番目のアプリを実行すると、16進エディターによる大まかな検査では、基本的に問題ないように見える出力ファイルが得られます。IOW、それはゼロバイトのファイルではないか、認識できないジブリッシュでいっぱいです。最初のアプリからの出力と同様の種類のジブリッシュでいっぱいです。ただし、AndroidもVLCも再生できません。

推測しなければならないのですが、パイプからの読み取りで何かを台無しにしていると思いますが、具体的にどこが間違っているのかわかりません。

助言がありますか?

前もって感謝します!

4

1 に答える 1

14

これはあなたの他の質問に対する私の答えに関連していると思います。 MediaPlayerがParcelFileDescriptorとcreatePipe()を操作している人はいますか?

おそらく、MediaRecorderがヘッダー情報を書き込もうとすると、パイプが閉じられます。

使用する場合:

recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

レコードにはヘッダー情報がなく、生のオーディオのみが含まれるため、レコードは正常に機能します。

于 2012-10-17T13:51:11.160 に答える