【问题标题】:record .wav format file in android using OmRecorder使用 OmRecorder 在 android 中录制 .wav 格式的文件
【发布时间】:2019-01-23 06:42:15
【问题描述】:

所以我正在尝试为用户录制音频并尝试在用户不说话时删除静音。

为此,我进行了很多搜索,发现您可以使用媒体记录器或录音机进行记录,然后对其进行转换并尝试分析块以检测静音。

好吧,对于刚开始使用 android 的人来说工作量太大,然后我发现这个项目已经在运行,你可以将它用作你只需要适应你的情况的依赖项。

这是链接:https://github.com/kailash09dabhi/OmRecorder

现在我的问题是,每当我尝试运行我的应用程序时,当我点击假设启动录制步骤的图像视图时,应用程序崩溃并自动关闭,我收到此错误: java.lang.RuntimeException: 无法从此文件 test.wav 构建 OutputStream

任何人都可以提出任何解决方案吗??

Manifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.authentric.audioenrol">

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

主活动:

public class MainActivity extends AppCompatActivity {

Recorder recorder;
ImageView recordButton;
CheckBox skipSilence;
private Button pauseResumeButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    getSupportActionBar().setTitle("Wav Recorder");
    setupRecorder();
    skipSilence = (CheckBox) findViewById(R.id.skipSilence);
    skipSilence.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
            if (isChecked) {
                setupNoiseRecorder();
            } else {
                setupRecorder();
            }
        }
    });
    recordButton = (ImageView) findViewById(R.id.recordButton);
    recordButton.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View view) {
            recorder.startRecording();
            skipSilence.setEnabled(false);
        }
    });
    findViewById(R.id.stopButton).setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View view) {
            try {
                recorder.stopRecording();
            } catch (IOException e) {
                e.printStackTrace();
            }
            skipSilence.setEnabled(true);
            recordButton.post(new Runnable() {
                @Override public void run() {
                    animateVoice(0);
                }
            });
        }
    });
    pauseResumeButton = (Button) findViewById(R.id.pauseResumeButton);
    pauseResumeButton.setOnClickListener(new View.OnClickListener() {
        boolean isPaused = false;

        @Override public void onClick(View view) {
            if (recorder == null) {
                Toast.makeText(MainActivity.this, "Please start recording first!",
                        Toast.LENGTH_SHORT).show();
                return;
            }
            if (!isPaused) {
                pauseResumeButton.setText(getString(R.string.resume_recording));
                recorder.pauseRecording();
                pauseResumeButton.postDelayed(new Runnable() {
                    @Override public void run() {
                        animateVoice(0);
                    }
                }, 100);
            } else {
                pauseResumeButton.setText(getString(R.string.pause_recording));
                recorder.resumeRecording();
            }
            isPaused = !isPaused;
        }
    });
}

private void setupRecorder() {
    recorder = OmRecorder.wav(
            new PullTransport.Default(mic(), new PullTransport.OnAudioChunkPulledListener() {
                @Override public void onAudioChunkPulled(AudioChunk audioChunk) {
                    animateVoice((float) (audioChunk.maxAmplitude() / 200.0));
                }
            }), file());
}

private void setupNoiseRecorder() {
    recorder = OmRecorder.wav(
            new PullTransport.Noise(mic(),
                    new PullTransport.OnAudioChunkPulledListener() {
                        @Override public void onAudioChunkPulled(AudioChunk audioChunk) {
                            animateVoice((float) (audioChunk.maxAmplitude() / 200.0));
                        }
                    },
                    new WriteAction.Default(),
                    new Recorder.OnSilenceListener() {
                        @Override public void onSilence(long silenceTime) {
                            Log.e("silenceTime", String.valueOf(silenceTime));
                            Toast.makeText(MainActivity.this, "silence of " + silenceTime + " detected",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }, 200
            ), file()
    );
}

private void animateVoice(final float maxPeak) {
    recordButton.animate().scaleX(1 + maxPeak).scaleY(1 + maxPeak).setDuration(10).start();
}

private PullableSource mic() {
    return new PullableSource.Default(
            new AudioRecordConfig.Default(
                    MediaRecorder.AudioSource.MIC, AudioFormat.ENCODING_PCM_16BIT,
                    AudioFormat.CHANNEL_IN_MONO, 44100
            )
    );
}

@NonNull private File file() {
    return new File(Environment.getExternalStorageDirectory(), "test.wav");
}
}

activityMain.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_screen"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@null"
    android:baselineAligned="false"
    android:clickable="false"
    android:orientation="vertical"
    android:padding="16dp">
    <TextView
    android:id="@+id/timerView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:paddingBottom="5dp"
    android:text="00:00:00"
    android:textColor="@android:color/black"
    android:textSize="55sp"
    android:textStyle="bold"/>


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="16dp"
        android:gravity="center"
        android:paddingBottom="8dp"
        android:text="click microphone to record"
        android:textAppearance="?android:textAppearanceMedium"
        android:textColor="@android:color/black"/>
    <Button
        android:id="@+id/pauseResumeButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/pause_recording"/>

    <LinearLayout
        android:id="@+id/containerView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/recordButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_microphone"/>

        <ImageView
            android:id="@+id/stopButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dp"
            android:paddingBottom="5dp"
            android:src="@drawable/ic_stop"/>
    </LinearLayout>


    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <CheckBox
            android:id="@+id/skipSilence"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="false"
            android:text="skip silence"/>


    </LinearLayout>

</LinearLayout>

【问题讨论】:

    标签: android voice-recording


    【解决方案1】:

    在提供的代码中,运行时不请求 WRITE_EXTERNAL_STORAGE 权限。它可能会在 Android 6+ 上导致上述 RuntimeException:

    java.lang.RuntimeException: could not build OutputStream from this file test.wav
        at omrecorder.AbstractRecorder.outputStream(AbstractRecorder.java:67)
        at omrecorder.AbstractRecorder.startRecording(AbstractRecorder.java:54)
        at ...
     Caused by: java.io.FileNotFoundException: /storage/emulated/0/test.wav (Permission denied)
        at java.io.FileOutputStream.open0(Native Method)
        at java.io.FileOutputStream.open(FileOutputStream.java:287)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:223)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:171)
        at omrecorder.AbstractRecorder.outputStream(AbstractRecorder.java:64)
        at omrecorder.AbstractRecorder.startRecording(AbstractRecorder.java:54) 
        at ...
    

    从 Android 6 (API 23) 开始,除了 AndroidManifest.xml 声明之外,危险权限(包括 WRITE_EXTERNAL_STORAGE)必须是requested at runtime

    以下代码片段检查是否授予权限,否则请求它:

    // ID to identify permission request
    private static final int MY_PERMISSION_REQUEST_ID = 1;
    
    // Check if permission is granted
    if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                 thisActivity,
                 new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                 MY_PERMISSION_REQUEST_ID);
    } else {
        // already granted, start OmRecorder
    }
    
    // Override in Activity to check the request result
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // granted, start OmRecorder
                } 
                return;
            }
        }
    }
    

    查看更详细的文档here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-17
      • 2014-07-27
      • 1970-01-01
      • 2013-06-16
      • 1970-01-01
      相关资源
      最近更新 更多