- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我正在尝试为用户录制音频并尝试在用户不说话时消除静音。
对于该措施,我搜索了很多,我发现您可以使用媒体记录器或录音机进行记录,然后将其转换并尝试分析 block 以检测静音。
嗯,对于刚开始使用 android 的人来说,工作量太大了,然后我发现这个项目已经在工作了,您可以将它用作依赖项,您只需要适应您的情况。
这是链接:https://github.com/kailash09dabhi/OmRecorder
现在我的问题是,每当我尝试运行我的应用程序时,当我点击应该启动记录步骤的 ImageView 时,应用程序崩溃并自动关闭,我得到这个错误: java.lang.RuntimeException: 无法从此文件 test.wav 构建 OutputStream
任何人都可以提出任何解决方案吗??
list .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>
主要 Activity :
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>
最佳答案
在提供的代码中,运行时不请求 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)开始,危险权限(包括WRITE_EXTERNAL_STORAGE)必须是requested at runtime ,除了 AndroidManifest.xml 声明。
以下代码 fragment 检查是否授予权限,否则请求权限:
// 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 .
关于android - 使用 OmRecorder 在 android 中录制 .wav 格式文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51821888/
所以我正在尝试为用户录制音频并尝试在用户不说话时消除静音。 对于该措施,我搜索了很多,我发现您可以使用媒体记录器或录音机进行记录,然后将其转换并尝试分析 block 以检测静音。 嗯,对于刚开始使用
我是一名优秀的程序员,十分优秀!