Android:在 Android 中录制音频,然后将音频读入 python
Android: Recording audio in Android and then reading audio into python
我需要在 Android 应用程序中录制音频,该应用程序需要导入 Python (ndarray) 以进行绘图和信号处理。这似乎是一个如此简单的想法。
我从一段简单的 AAC/MPEG4 记录代码开始。录音效果很好。我可以在 Android phone (Nexus 5X) 和 Mac (Quicktime) 上播放。没问题!正确的?!?但是找到 Android 和 Python 之间匹配的 codec/formats 似乎并不简单。我在想是不是Android写的file/codec格式是非标准的,FFMPEG无法读取。
如果是这样,什么是好的音频format/codec可以简单地写入Android并读入数组Python(2.7.x)。谢谢。
详情:
这是 android 代码的缩写形式:
private final int AUDIO_SAMPLE_RATE = 16000;
private final String FILE_EXTENSION = "m4a"; // Audio file extension
mAbsolutePathFile = workingDir + "/" + mFilename + FILE_EXTENSION;
mMediaRecording = new MediaRecorder();
mMediaRecording.setAudioSource (MediaRecorder.AudioSource.MIC);
mMediaRecording.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecording.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecording.setAudioSamplingRate(AUDIO_SAMPLE_RATE);
mMediaRecording.setOutputFile(mAbsolutePathFile);
mMediaRecording.prepare();
mMediaRecording.start();
正如我提到的,结果音频在 Android 和 MacOS 中都播放得很好,所以一切看起来都很好。我做了一些搜索以找到 AAC 音频的 python 包,pydub
看起来是最简单的(我试过 audiotools,但找不到示例代码)。要安装 pydub
,我遵循了 instructions:
pip install pydub
和
brew install libav --with-libvorbis --with-sdl --with-theora
和
brew install ffmpeg --with-libvorbis --with-ffplay --with-theora
根据讨论 (here),我测试了 ffmpeg
并且它确实从命令行执行:
$ffmpeg
ffmpeg version 3.2.2 Copyright (c) 2000-2016 the FFmpeg developers
built with Apple LLVM version 8.0.0 (clang-800.0.42.1)
但是当我尝试使用 Python:
读取文件时
import pydub
pydub.AudioSegment.from_file("sensorlog_2017-02-03_12-50-25-345_Dev26c5_Loc27_TypeAUDIO.m4a", "aac")
我得到:
Traceback (most recent call last):
File "...anaconda2/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 2881, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-8-607e3f2a62c3>", line 1, in <module>
pydub.AudioSegment.from_file("sensorlog_2017-02-03_12-50-25-345_Dev26c5_Loc27_TypeAUDIO.m4a", "aac")
File ".../anaconda2/lib/python2.7/site-packages/pydub/audio_segment.py", line 472, in from_file
raise CouldntDecodeError("Decoding failed. ffmpeg returned error code: {0}\n\nOutput from ffmpeg/avlib:\n\n{1}".format(p.returncode, p_err))
CouldntDecodeError: Decoding failed. ffmpeg returned error code: 1
Output from ffmpeg/avlib:
avconv version 11.4, Copyright (c) 2000-2014 the Libav developers
built on Feb 3 2017 12:09:15 with Apple LLVM version 8.0.0 (clang-800.0.42.1)
[aac @ 0x7ff30001cc00] get_buffer() failed
[aac @ 0x7ff30001cc00] channel element 3.14 is not allocated
[aac @ 0x7ff30001cc00] Sample rate index in program config element does not match the sample rate index configured by the container.
[aac @ 0x7ff30001cc00] Input buffer exhausted before END element found
[aac @ 0x7ff30001cc00] More than one AAC RDB per ADTS frame is not implemented. Update your Libav version to the newest one from Git. If the problem still occurs, it means that your file has a feature which has not been implemented.
[aac @ 0x7ff30001cc00] Error decoding AAC frame header.
[aac @ 0x7ff300001000] Could not find codec parameters (Audio: aac, 4.0, fltp, 213 kb/s)
[aac @ 0x7ff300001000] Estimating duration from bitrate, this may be inaccurate
/var/folders/cm/1r6x6rbj7hn_51qvfjzj7nx80000gn/T/tmps7b8Gf: could not find codec parameters
综上所述,这是Android和FFMPEG之间的冲突吗?我应该使用不同的 codec/format 吗?我应该使用不同的 Python 音频库吗?
谢谢。
在 pydub 的 GitHub issues 中有一些额外的讨论,但对于未来的流浪者,我相信解决方案是使用 "mp4" 作为格式
from pydub import AudioSegment
sound = AudioSegment.from_file("./sensorlog.m4a", format="mp4")
旁注:如果您无法找出正确的格式,可以完全省略格式参数,pydub/ffmpeg/avconv/whoever 会尝试找出正确的格式。
sound = AudioSegment.from_file("./sensorlog.m4a")
您可能还会发现尝试 pydub.utils.mediainfo()
很有用,尽管根据您的 ffmpeg/avconv 安装,它可能可用也可能不可用(它在内部使用 ffprobe)
>>> from pydub.utils import mediainfo
>>> mediainfo("./sensorlog.m4a")
{u'DISPOSITION': {u'attached_pic': u'0',
u'clean_effects': u'0',
u'comment': u'0',
u'default': u'1',
u'dub': u'0',
u'forced': u'0',
u'hearing_impaired': u'0',
u'karaoke': u'0',
u'lyrics': u'0',
u'original': u'0',
u'timed_thumbnails': u'0',
u'visual_impaired': u'0'},
u'TAG': {u'com.android.version': u'7.0',
u'compatible_brands': u'isommp42',
u'creation_time': u'2017-02-03T20:50:33.000000Z',
u'handler_name': u'SoundHandle',
u'language': u'eng',
u'major_brand': u'mp42',
u'minor_version': u'0'},
u'avg_frame_rate': u'0/0',
u'bit_rate': u'15539',
u'bits_per_raw_sample': u'N/A',
u'bits_per_sample': u'0',
u'channel_layout': u'mono',
u'channels': u'1',
u'codec_long_name': u'AAC (Advanced Audio Coding)',
u'codec_name': u'aac',
u'codec_tag': u'0x6134706d',
u'codec_tag_string': u'mp4a',
u'codec_time_base': u'1/8000',
u'codec_type': u'audio',
u'duration': u'7.808000',
u'duration_ts': u'62464',
u'filename': u'/Users/jiaaro/Downloads/sensorlog_2017-02-03_12-50-25-345_Dev26c5_Loc27_ActvAppTesting_TypeAUDIO.m4a',
u'format_long_name': u'QuickTime / MOV',
u'format_name': u'mov,mp4,m4a,3gp,3g2,mj2',
u'id': u'N/A',
u'index': u'0',
u'max_bit_rate': u'12200',
u'nb_frames': u'61',
u'nb_programs': u'0',
u'nb_read_frames': u'N/A',
u'nb_read_packets': u'N/A',
u'nb_streams': u'1',
u'probe_score': u'100',
u'profile': u'LC',
u'r_frame_rate': u'0/0',
u'sample_fmt': u'fltp',
u'sample_rate': u'8000',
u'size': u'15167',
u'start_pts': u'0',
u'start_time': u'0.000000',
u'time_base': u'1/8000'}
我需要在 Android 应用程序中录制音频,该应用程序需要导入 Python (ndarray) 以进行绘图和信号处理。这似乎是一个如此简单的想法。
我从一段简单的 AAC/MPEG4 记录代码开始。录音效果很好。我可以在 Android phone (Nexus 5X) 和 Mac (Quicktime) 上播放。没问题!正确的?!?但是找到 Android 和 Python 之间匹配的 codec/formats 似乎并不简单。我在想是不是Android写的file/codec格式是非标准的,FFMPEG无法读取。
如果是这样,什么是好的音频format/codec可以简单地写入Android并读入数组Python(2.7.x)。谢谢。
详情: 这是 android 代码的缩写形式:
private final int AUDIO_SAMPLE_RATE = 16000;
private final String FILE_EXTENSION = "m4a"; // Audio file extension
mAbsolutePathFile = workingDir + "/" + mFilename + FILE_EXTENSION;
mMediaRecording = new MediaRecorder();
mMediaRecording.setAudioSource (MediaRecorder.AudioSource.MIC);
mMediaRecording.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecording.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecording.setAudioSamplingRate(AUDIO_SAMPLE_RATE);
mMediaRecording.setOutputFile(mAbsolutePathFile);
mMediaRecording.prepare();
mMediaRecording.start();
正如我提到的,结果音频在 Android 和 MacOS 中都播放得很好,所以一切看起来都很好。我做了一些搜索以找到 AAC 音频的 python 包,pydub
看起来是最简单的(我试过 audiotools,但找不到示例代码)。要安装 pydub
,我遵循了 instructions:
pip install pydub
和
brew install libav --with-libvorbis --with-sdl --with-theora
和
brew install ffmpeg --with-libvorbis --with-ffplay --with-theora
根据讨论 (here),我测试了 ffmpeg
并且它确实从命令行执行:
$ffmpeg
ffmpeg version 3.2.2 Copyright (c) 2000-2016 the FFmpeg developers
built with Apple LLVM version 8.0.0 (clang-800.0.42.1)
但是当我尝试使用 Python:
读取文件时import pydub
pydub.AudioSegment.from_file("sensorlog_2017-02-03_12-50-25-345_Dev26c5_Loc27_TypeAUDIO.m4a", "aac")
我得到:
Traceback (most recent call last):
File "...anaconda2/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 2881, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-8-607e3f2a62c3>", line 1, in <module>
pydub.AudioSegment.from_file("sensorlog_2017-02-03_12-50-25-345_Dev26c5_Loc27_TypeAUDIO.m4a", "aac")
File ".../anaconda2/lib/python2.7/site-packages/pydub/audio_segment.py", line 472, in from_file
raise CouldntDecodeError("Decoding failed. ffmpeg returned error code: {0}\n\nOutput from ffmpeg/avlib:\n\n{1}".format(p.returncode, p_err))
CouldntDecodeError: Decoding failed. ffmpeg returned error code: 1
Output from ffmpeg/avlib:
avconv version 11.4, Copyright (c) 2000-2014 the Libav developers
built on Feb 3 2017 12:09:15 with Apple LLVM version 8.0.0 (clang-800.0.42.1)
[aac @ 0x7ff30001cc00] get_buffer() failed
[aac @ 0x7ff30001cc00] channel element 3.14 is not allocated
[aac @ 0x7ff30001cc00] Sample rate index in program config element does not match the sample rate index configured by the container.
[aac @ 0x7ff30001cc00] Input buffer exhausted before END element found
[aac @ 0x7ff30001cc00] More than one AAC RDB per ADTS frame is not implemented. Update your Libav version to the newest one from Git. If the problem still occurs, it means that your file has a feature which has not been implemented.
[aac @ 0x7ff30001cc00] Error decoding AAC frame header.
[aac @ 0x7ff300001000] Could not find codec parameters (Audio: aac, 4.0, fltp, 213 kb/s)
[aac @ 0x7ff300001000] Estimating duration from bitrate, this may be inaccurate
/var/folders/cm/1r6x6rbj7hn_51qvfjzj7nx80000gn/T/tmps7b8Gf: could not find codec parameters
综上所述,这是Android和FFMPEG之间的冲突吗?我应该使用不同的 codec/format 吗?我应该使用不同的 Python 音频库吗? 谢谢。
在 pydub 的 GitHub issues 中有一些额外的讨论,但对于未来的流浪者,我相信解决方案是使用 "mp4" 作为格式
from pydub import AudioSegment
sound = AudioSegment.from_file("./sensorlog.m4a", format="mp4")
旁注:如果您无法找出正确的格式,可以完全省略格式参数,pydub/ffmpeg/avconv/whoever 会尝试找出正确的格式。
sound = AudioSegment.from_file("./sensorlog.m4a")
您可能还会发现尝试 pydub.utils.mediainfo()
很有用,尽管根据您的 ffmpeg/avconv 安装,它可能可用也可能不可用(它在内部使用 ffprobe)
>>> from pydub.utils import mediainfo
>>> mediainfo("./sensorlog.m4a")
{u'DISPOSITION': {u'attached_pic': u'0',
u'clean_effects': u'0',
u'comment': u'0',
u'default': u'1',
u'dub': u'0',
u'forced': u'0',
u'hearing_impaired': u'0',
u'karaoke': u'0',
u'lyrics': u'0',
u'original': u'0',
u'timed_thumbnails': u'0',
u'visual_impaired': u'0'},
u'TAG': {u'com.android.version': u'7.0',
u'compatible_brands': u'isommp42',
u'creation_time': u'2017-02-03T20:50:33.000000Z',
u'handler_name': u'SoundHandle',
u'language': u'eng',
u'major_brand': u'mp42',
u'minor_version': u'0'},
u'avg_frame_rate': u'0/0',
u'bit_rate': u'15539',
u'bits_per_raw_sample': u'N/A',
u'bits_per_sample': u'0',
u'channel_layout': u'mono',
u'channels': u'1',
u'codec_long_name': u'AAC (Advanced Audio Coding)',
u'codec_name': u'aac',
u'codec_tag': u'0x6134706d',
u'codec_tag_string': u'mp4a',
u'codec_time_base': u'1/8000',
u'codec_type': u'audio',
u'duration': u'7.808000',
u'duration_ts': u'62464',
u'filename': u'/Users/jiaaro/Downloads/sensorlog_2017-02-03_12-50-25-345_Dev26c5_Loc27_ActvAppTesting_TypeAUDIO.m4a',
u'format_long_name': u'QuickTime / MOV',
u'format_name': u'mov,mp4,m4a,3gp,3g2,mj2',
u'id': u'N/A',
u'index': u'0',
u'max_bit_rate': u'12200',
u'nb_frames': u'61',
u'nb_programs': u'0',
u'nb_read_frames': u'N/A',
u'nb_read_packets': u'N/A',
u'nb_streams': u'1',
u'probe_score': u'100',
u'profile': u'LC',
u'r_frame_rate': u'0/0',
u'sample_fmt': u'fltp',
u'sample_rate': u'8000',
u'size': u'15167',
u'start_pts': u'0',
u'start_time': u'0.000000',
u'time_base': u'1/8000'}