我们在做Android平台RTMP推送和GB28181设备对接的时候,遇到这样的问题,有的设备,麦克风采集出来的audio,音量过高或过低,特别是有些设备,采集到的麦克风声音过低,导致播放端听不清前端采集的audio,这时候,就需要针对采集到的audio,做音量放大处理。
先说如何采集,android平台通用的做法是采集audiorecord,设置audio的采样率和channels,为了便于数据进行二次处理,或者同时投递给多个实例,我们的做法,是把采集到的audio,回调上来,然后再设置到jni层:
void CheckInitAudioRecorder() { if (audioRecord_ == null) { audioRecord_ = new NTAudioRecordV2(this); } if (audioRecord_ != null) { Log.i(TAG, "CheckInitAudioRecorder call audioRecord_.start()+++..."); audioRecordCallback_ = new NTAudioRecordV2CallbackImpl(); audioRecord_.AddCallback(audioRecordCallback_); audioRecord_.Start(16000, 1); Log.i(TAG, "CheckInitAudioRecorder call audioRecord_.start()---..."); } }
audio回调处理:
class NTAudioRecordV2CallbackImpl implements NTAudioRecordV2Callback { @Override public void onNTAudioRecordV2Frame(ByteBuffer data, int size, int sampleRate, int channel, int per_channel_sample_number) { if ((isPushingRtmp || isRTSPPublisherRunning) && publisherHandle != 0) { libPublisher.SmartPublisherOnPCMData(publisherHandle, data, size, sampleRate, channel, per_channel_sample_number); } } }
如何实现audio音量放大?
输入音量的调节,需要注意的是,处理音频音量时要尽可能线性,以防止溢出。我们针对jni层的设计如下:
/** * 设置输入音量, 这个接口一般不建议调用, 在一些特殊情况下可能会用, 一般不建议放大音量 * * @param index: 一般是0和1, 如果没有混音的只用0, 有混音的话, 0,1分别设置音量 * * @param volume: 音量,默认是1.0,范围是[0.0, 5.0], 设置成0静音, 1音量不变 * * @return {0} if successful */ public native int SmartPublisherSetInputAudioVolume(long handle, int index, float volume);
调用逻辑如下:
in_audio_volume_selector_ = (Spinner) findViewById(R.id.in_audio_volume_selector); final String[] in_audio_volume_sel = new String[]{"0", "0.2", "0.5", "0.8", "1", "1.5", "2", "2.5", "3", "3.5", "4", "4.5", "5"}; ArrayAdapter<String> adapter_in_audio_volume = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, in_audio_volume_sel); adapter_in_audio_volume.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); in_audio_volume_selector_.setAdapter(adapter_in_audio_volume); in_audio_volume_selector_.setSelection(4, true); in_audio_volume_selector_.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Log.i(TAG, "Currently audio volume choosing: " + in_audio_volume_sel[position]); in_audio_volume_ = Float.parseFloat(in_audio_volume_sel[position]); Log.i(TAG, "Choose audio volume=" + in_audio_volume_); if (isPushingRtmp || isRTSPPublisherRunning) { if (libPublisher != null && publisherHandle != 0) { libPublisher.SmartPublisherSetInputAudioVolume(publisherHandle, 0, in_audio_volume_); } } } @Override public void onNothingSelected(AdapterView<?> parent) { } });
感兴趣的开发者,可以参考实现,需要注意的是,audio采集可能不限于麦克风,也可能是第三方数据采集源,所以接口设计的时候,尽量考虑在jni层针对数据源做处理,此外,除了音量放大外,还可以做音量缩小,或者实时静音。