如何让用应用公园制作录音录屏录音软件下载功能的apk

Android录音实现――使用AtudioRecord
最近在做android中录音录屏的功能,以前也是从未接触多媒体这块,然后从不会到一点点的摸索,参考大神们的代码,到现在算是入门了,今天就总结一下android中的录音部分,后面总结录屏。
在android中实现录音共有三种方式:
通过意图捕获音频。这是android中最简单的一种方式,就是通过一个意图利用已有的、提供录制功能的应用程序。android系统中都会再带一个录音程序,我们可以通过意图来调用这个录音程序,从而实现录音功能。MediaRecorder类实现录音。MediaRecorder类是android中用来捕获音频和视频的多媒体类,通过这种方式录制音频也是比较简单的。通过设置音频源,输出格式,设置音频编解码器进行编解码,最后将音频输出到文件中。AudioRecord录制原始音频。这种方式相对于前两种比较麻烦,需要我们自己处理的事情较多,因此也是最灵活的。AudioRecord允许访问原始音频流,这种音频流是不能直接进行播放的,需要使用AudioTrack来进行播放原始音频。如果要使用这种方式来将音频保存到文件中,并可像MP3文件一样直接打开的话,就需要对原始音频进行编解码,然后用混合器(Muxer)进行输出到文件中。
我所用到的是第三种方式来实现录音的,因为我需要将音频添加到视频中去,因此得选用第三中最灵活的方式。
使用AudioRecord录制音频并不难,但是要将原始音频进行编码并输出到一个可播放的文件中就有点麻烦。先说说实现这个功能的大概思路:我们需要两个任务,一个任务用来进行采集音频数据,在采集音频数据的同时将音频数据不断的发送给编码的任务,将这些数据按照指定格式进行编码,然后输出到文件中。
使用AudioRecord捕获原始音频流。采集工作很简单,我们只需要构造一个AudioRecord对象,然后传入各种不同配置的参数即可。
1.音频源:我们可以使用麦克风作为采集音频的数据源。
2.采样率:一秒钟对声音数据的采样次数,采样率越高,音质越好。
3.音频通道:单声道,双声道等,
4.音频格式:一般选用PCM格式,即原始的音频样本。
5.缓冲区大小:音频数据写入缓冲区的总数,可以通过AudioRecord.getMinBufferSize获取最小的缓冲区。(将音频采集到缓冲区中然后再从缓冲区中读取)。
package com.creativeboy.audioandvideocapture.
import android.media.AudioF
import android.media.AudioR
import android.media.MediaC
import android.media.MediaCodecI
import android.media.MediaF
import android.media.MediaM
import android.media.MediaR
import android.os.E
import android.util.L
import java.io.BufferedOutputS
import java.io.DataOutputS
import java.io.F
import java.io.FileNotFoundE
import java.io.FileOutputS
import java.io.IOE
import java.nio.ByteB
import java.util.concurrent.atomic.AtomicB
* Created by heshaokang on .
public class AudioRecorder {
private static final String TAG = &AudioRecorder&;
private static final int SAMPLE_RATE = 44100; //采样率(CD音质)
private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO; //音频通道(单声道)
private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; //音频格式
private static final int AUDIO_SOURCE = MediaRecorder.AudioSource.MIC;
//音频源(麦克风)
private static boolean is_recording =
public static File recordF
private AudioEncoder audioE
private static AudioR
private RecorderTask recorderTask = new RecorderTask();
private AudioRecorder(File file){
recordFile =
public static AudioRecorder getInstance(File file) {
return new AudioRecorder(file);
public void setAudioEncoder(AudioEncoder audioEncoder) {
this.audioEncoder = audioE
public void startAudioRecording() {
new Thread(recorderTask).start();
public void stopAudioRecording() {
is_recording =
class RecorderTask implements Runnable {
int bufferReadResult = 0;
public int samples_per_frame = 2048;
public void run() {
long audioPresentationTimeNs; //音频时间戳 pts
//获取最小缓冲区大小
int bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE,CHANNEL_CONFIG,AUDIO_FORMAT);
AudioRecord audioRecord = new AudioRecord(
AUDIO_SOURCE,
SAMPLE_RATE,
CHANNEL_CONFIG,
//音频通道
AUDIO_FORMAT,
//音频格式
bufferSizeInBytes //缓冲区
audioRecord.startRecording();
is_recording =
Log.v(TAG, &recordFile.getAbsolutepath---& + recordFile.getAbsolutePath());
while(is_recording) {
byte[] buffer = new byte[samples_per_frame];
audioPresentationTimeNs = System.nanoTime();
//从缓冲区中读取数据,存入到buffer字节数组数组中
bufferReadResult = audioRecord.read(buffer,0,samples_per_frame);
//判断是否读取成功
if(bufferReadResult == AudioRecord.ERROR_BAD_VALUE || bufferReadResult == AudioRecord.ERROR_INVALID_OPERATION)
Log.e(TAG, &Read error&);
if(audioRecord!=null) {
audioEncoder.offerAudioEncoder(buffer,audioPresentationTimeNs);
if(audioRecord!=null) {
audioRecord.setRecordPositionUpdateListener(null);
audioRecord.stop();
audioRecord.release();
audioRecord =
使用MediaCodec进行音频编码.
MediaCodec是android的一个编解码类。将获取到的原始音频流先进行特定的解码,然后进行数据处理,再编码为指定的格式。具体可参考这篇博客:http://blog.csdn.net/mouse_1894/article/details/
MediaMuxer 这是一个混合器,用来将编码好的音频数据输出到文件。
package com.creativeboy.audioandvideocapture.
import android.media.MediaC
import android.media.MediaCodecI
import android.media.MediaF
import android.media.MediaM
import android.util.L
import java.io.IOE
import java.nio.ByteB
import java.util.concurrent.ExecutorS
import java.util.concurrent.E
* Created by heshaokang on .
对音频数据进行编码
public class AudioEncoder {
private static final String TAG = &AudioEncoder&;
private MediaCodec mAudioC
//音频编解码器
private MediaFormat mAudioF
private static final String AUDIO_MIME_TYPE = &audio/mp4a-latm&; //音频类型
private static final int SAMPLE_RATE = 44100; //采样率(CD音质)
private TrackIndex mAudioTrackIndex = new TrackIndex();
private MediaMuxer mMediaM
private boolean mMuxerStart = //混合器启动的标志
private MediaCodec.BufferInfo mAudioBufferI
private static long audioBytesReceived = 0;
//接收到的音频数据 用来设置录音起始时间的
private long audioStartT
private String recordF
private boolean eosReceived =
//终止录音的标志
private ExecutorService encodingService = Executors.newSingleThreadExecutor(); //序列化线程任务
//枚举值 一个用来标志编码 一个标志编码完成
enum EncoderTaskType {ENCODE_FRAME,FINALIZE_ENCODER};
public AudioEncoder() {
recordFile = AudioRecorder.recordFile.getAbsolutePath();
prepareEncoder();
class TrackIndex {
int index = 0;
public void prepareEncoder() {
eosReceived =
audioBytesReceived = 0;
mAudioBufferInfo = new MediaCodec.BufferInfo();
mAudioFormat = new MediaFormat();
mAudioFormat.setString(MediaFormat.KEY_MIME, AUDIO_MIME_TYPE);
mAudioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
mAudioFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE,SAMPLE_RATE);
mAudioFormat.setInteger(MediaFormat.KEY_BIT_RATE, 128000);
mAudioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
mAudioFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE,16384);
mAudioCodec = MediaCodec.createEncoderByType(AUDIO_MIME_TYPE);
mAudioCodec.configure(mAudioFormat,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);
mAudioCodec.start();
mMediaMuxer = new MediaMuxer(recordFile,MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
} catch (IOException e) {
e.printStackTrace();
//此方法 由AudioRecorder任务调用 开启编码任务
public void offerAudioEncoder(byte[] input,long presentationTimeStampNs) {
if(!encodingService.isShutdown()) {
Log.d(TAG,&encodingService--submit&);
encodingService.submit(new AudioEncodeTask(this,input,presentationTimeStampNs));
//发送音频数据和时间进行编码
public void _offerAudioEncoder(byte[] input,long pts) {
if(audioBytesReceived==0) {
audioStartTime =
audioBytesReceived+=input.
drainEncoder(mAudioCodec,mAudioBufferInfo,mAudioTrackIndex,false);
ByteBuffer[] inputBuffers = mAudioCodec.getInputBuffers();
int inputBufferIndex = mAudioCodec.dequeueInputBuffer(-1);
Log.d(TAG,&inputBufferIndex--&+inputBufferIndex);
if(inputBufferIndex&=0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(input);
//录音时长
long presentationTimeUs = (pts - audioStartTime)/1000;
Log.d(&hsk&,&presentationTimeUs--&+presentationTimeUs);
if(eosReceived) {
mAudioCodec.queueInputBuffer(inputBufferIndex, 0, input.length, presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
closeEncoder(mAudioCodec, mAudioBufferInfo, mAudioTrackIndex);
closeMuxer();
encodingService.shutdown();
mAudioCodec.queueInputBuffer(inputBufferIndex,0,input.length,presentationTimeUs,0);
}catch (Throwable t) {
Log.e(TAG, &_offerAudioEncoder exception&);
public void drainEncoder(MediaCodec encoder,MediaCodec.BufferInfo bufferInfo,TrackIndex trackIndex ,boolean endOfStream) {
final int TIMEOUT_USEC = 100;
ByteBuffer[] encoderOutputBuffers = encoder.getOutputBuffers();
while(true) {
int encoderIndex = encoder.dequeueOutputBuffer(bufferInfo,TIMEOUT_USEC);
Log.d(&hsk&,&encoderIndex---&+encoderIndex);
if(encoderIndex==_TRY_AGAIN_LATER) {
//没有可进行混合的输出流数据 但还没有结束录音 此时退出循环
Log.d(TAG,&info_try_again_later&);
if(!endOfStream)
Log.d(TAG, &no output available, spinning to await EOS&);
}else if(encoderIndex== _OUTPUT_FORMAT_CHANGED) {
//只会在第一次接收数据前 调用一次
if(mMuxerStart)
throw new RuntimeException(&format 在muxer启动后发生了改变&);
MediaFormat newFormat = encoder.getOutputFormat();
trackIndex.index = mMediaMuxer.addTrack(newFormat);
mMediaMuxer.start();
mMuxerStart =
}else if(encoderIndex&0) {
Log.w(TAG,&encoderIndex 非法&+encoderIndex);
ByteBuffer encodeData = encoderOutputBuffers[encoderIndex];
if (encodeData==null) {
throw new RuntimeException(&编码数据为空&);
if(bufferInfo.size!=0) {
if(!mMuxerStart) {
throw new RuntimeException(&混合器未开启&);
encodeData.position(bufferInfo.offset);
encodeData.limit(bufferInfo.offset + bufferInfo.size);
mMediaMuxer.writeSampleData(trackIndex.index,encodeData,bufferInfo);
encoder.releaseOutputBuffer(encoderIndex,false);
//退出循环
if((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM)!=0) {
* 关闭编码
* @param encoder
* @param bufferInfo
public void closeEncoder(MediaCodec encoder,MediaCodec.BufferInfo bufferInfo,TrackIndex trackIndex) {
drainEncoder(encoder,bufferInfo,trackIndex,true);
encoder.stop();
encoder.release();
* 关闭混合器
public void closeMuxer() {
mMediaMuxer.stop();
mMediaMuxer.release();
mMediaMuxer =
mMuxerStart =
//发送终止编码信息
public void stop() {
if(!encodingService.isShutdown()) {
encodingService.submit(new AudioEncodeTask(this,EncoderTaskType.FINALIZE_ENCODER));
//终止编码
public void _stop() {
eosReceived =
Log.d(TAG,&停止编码&);
* 音频编码任务
class AudioEncodeTask implements Runnable {
private static final String TAG = &AudioEncoderTask&;
private boolean is_initialized =
private AudioE
private byte[] audio_
private EncoderTaskT
//进行编码任务时 调用此构造方法
public AudioEncodeTask(AudioEncoder encoder,byte[] audio_data,long pts) {
this.encoder =
this.audio_data = audio_
this.pts =
is_initialized =
this.type = EncoderTaskType.ENCODE_FRAME;
//这里是有数据的
Log.d(TAG,&AudioData--&+audio_data);
Log.d(TAG,&pts--&+pts);
//当要停止编码任务时 调用此构造方法
public AudioEncodeTask(AudioEncoder encoder,EncoderTaskType type) {
this.type =
if(type==EncoderTaskType.FINALIZE_ENCODER) {
this.encoder =
is_initialized =
Log.d(TAG,&完成...&);
private void encodeFrame() {
Log.d(TAG,&audio_data---encoder--&+audio_data+& &+encoder);
if(audio_data!=null && encoder!=null) {
encoder._offerAudioEncoder(audio_data,pts);
audio_data =
//终止编码
private void finalizeEncoder() {
encoder._stop();
public void run() {
Log.d(TAG,&is_initialized--&+is_initialized);
if(is_initialized) {
switch(type) {
case ENCODE_FRAME:
//进行编码
encodeFrame();
case FINALIZE_ENCODER:
//完成编码
finalizeEncoder();
is_initialized =
//打印错误日志
Log.e(TAG,&AudioEncoderTask is not initiallized&);
具体代码:/hsk256/RecordAudioAndVideo
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'中戏2016级新生新生开学报到,软萌妹子主打清纯牌。
连续在14年间强奸、杀害多名女性的犯罪嫌疑人落网。
声明:本文由入驻搜狐公众平台的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
  如今人们在移动终端上花费的时间越来越多,这也就促使了手机APP软件制作行业的迅速发展,对于一个企业或者个人来说,拥有属于自己APP软件,能节省很多物力以及人力,而请专门的APP外包公司,高昂的价格,制作周期长无疑又成为了钳制了抢占商机的痛脚。于是越来越多的企业或者个人都认为自己制作APP是一个很好的选择,但是APP怎么制作,不会编程就没有机会亲手制作一款称心的APP了吗?应用公园作为国内领先的手机APP在线制作平台,让人人都能成为“开发商”!
  那应用公园与专门的APP外包公司相比又有哪些优势了?针对APP怎么制作这一问题,它又提供怎样的解决方案?
  海量模板一点即通 人人都是开发商
  应用公园作为国内领先的手机APP在线制作平台,采用了简单易懂的纯图形操作。应用公园提供了窗口化操作的先进性我用一个比喻来说,那就像是比尔盖茨发明了windows系统,让用户告别了DOS命令!在应用公园APP怎么制作?应用公园提供优质模板库供用户选择使用,点击套用即可获得全方位的数字包装,模块化管理,想用什么拖什么,图片文字创意模块一个不能少,人人都做APP开发商!
  海量模板一点即通 人人都是开发商
  专业客户更需要充满诚意、充满创意的定制APP,这就需要更多的控件与插件支持,那么APP怎么制作?在应用公园里强大的控件式的操作让你轻松打造私人APP。顶部导航控件、宫格控件、列表控件、底部导航控件等十数种控件分类,让制作者能将自己想灵感,通过鼠标轻松滑动,控制成型板块加入这些控件之中,再加上自己的文字与图片,一款充满诚意的APP就诞生了,整个过程简单易操作,过程一目了然!比起传统APP制作团队高昂的费用与长达数十周的制作周期,应用公园让你轻松“上天”。
  自己运营APP 后台无忧有保障
  很多人问专门的APP制作团队怎么制作APP,项目完结后的后台管理与维护又该如何进行。交由其他团队制作APP的最大弊端无疑担心APP留有“后门”以及项目转移、后期维护的问题。而在应用公园自己制作手机app,完善的后台管理让制作者对自己的APP运营情况一目了然,数据化管理透明高效,自己运营!高级控件中包含产品、个人中心、在线支付、咨询、搜索等控件,而加上运用管理如子账号管理、统计信息、会员管理、订单管理、产品管理等管理功能,就能实现企业和客户对接,完成订单等过程。
  相比于专门的APP外包公司,应用公园的APP制作简单易上手,APP怎么制作也就不再是一个难题,APP市场如火如荼,不如来应用公园做一次自己的APP“开发商”。
  文章来源:
欢迎举报抄袭、转载、暴力色情及含有欺诈和虚假信息的不良文章。
请先登录再操作
请先登录再操作
微信扫一扫分享至朋友圈
搜狐公众平台官方账号
生活时尚&搭配博主 /生活时尚自媒体 /时尚类书籍作者
搜狐网教育频道官方账号
全球最大华文占星网站-专业研究星座命理及测算服务机构
应用公园为广大用户分享APP行业最新资讯,分享APP制作、...
主演:黄晓明/陈乔恩/乔任梁/谢君豪/吕佳容/戚迹
主演:陈晓/陈妍希/张馨予/杨明娜/毛晓彤/孙耀琦
主演:陈键锋/李依晓/张迪/郑亦桐/张明明/何彦霓
主演:尚格?云顿/乔?弗拉尼甘/Bianca Bree
主演:艾斯?库珀/ 查宁?塔图姆/ 乔纳?希尔
baby14岁写真曝光
李冰冰向成龙撒娇争宠
李湘遭闺蜜曝光旧爱
美女模特教老板走秀
曝搬砖男神奇葩择偶观
柳岩被迫成赚钱工具
大屁小P虐心恋
匆匆那年大结局
乔杉遭粉丝骚扰
男闺蜜的尴尬初夜
客服热线:86-10-
客服邮箱:利用应用公园制作的APP版权归谁所有?
你注册的时候肯定没有仔细阅读用户协议。5、 知识产权声明5.1 应用公园所提供的网络服务的相关著作权、专利权、商标权、商业秘密及其它任何所有权或权利,均属本公司所有。非经本公司的同意,任何人或用户均不得擅自下载、复制、传输、改编、编辑,否则应负所有法律责任。本公司拥有向用户提供网络服务过程中所产生并储存于应用公园服务器中的任何数据信息的所有权。用户不得在未获得本公司允许的情况下,私自通过不法途径获取软件源代码。软件源代码归本公司所有。国内的服务协议,大多数都是「亲爱的用户,我是你爹」或者「亲爱的用户,我是你亲爹」。有良心的没多少了。
免费的应用就是上面的声明中的归与应用公园所有,付费的因为签署合同,所以是归购买的人
已有帐号?
无法登录?
社交帐号登录努比亚同声录屏功能强悍让分享更随心所欲
| 来源: 米娜时尚网 | 编辑:minaed
[本文导读]随着4月19日努比亚智能手机新品发布会的日益临近,互联网上关于其新品的消息越来越聚焦。除了明确指向将发旗下小牛系列新品Z11 mini外,还曝光出小屏幕、大内存、4G+全网通、Volt
随着4月19日努比亚智能手机新品发布会的日益临近,互联网上关于其新品的消息越来越聚焦。除了明确指向将发旗下小牛系列新品Z11 mini外,还曝光出小屏幕、大内存、4G+全网通、Volte等亮点功能。就在昨天,努比亚智能手机总经理、nubia品牌联合创始人倪飞通过个人微博录制了一段关于新机全新UI的小视频,迫不及待的分享出新机又一亮点。
视频中,倪飞倾情献声录制了自己玩游戏的整个过程,并表示是用自家手机的&超级截图&功能完成的。从视频中可以看到,这项名为超级截图具有录屏功能,可以实现屏幕内容和手机录音同步输出,实现手机内部音效和外部录音双轨。之前像vivo推出的类似功能只是提供录屏功能,并不能将手机外的声音收入进去。
可以预见,这项功能未来将适用更多场景,让分享更加便捷。例如,手游用户可在不借助第三方的软件情况下分享自己的战绩;想要远程指导父母手机操作方法,自己录音并演示出来即可分享。相较于单纯的截屏很难直观的展现手机操作过程,超级截图可以全面解决这样的问题。
此外,我们还注意到一个细节,倪飞录制的视频中,他的手机桌面上有两个微信应用与两个QQ应用,也再度证实了此前曝光的新品的应用分身功能,该功能的加入,必将平衡用户的工作和生活,完美的将公开和隐私进行分离掌控。
此次超级截图功能的加入,或将预示努比亚将借新品推出全新UI,,加之之前曝光的一系列功能,nubia Z11mini俨然已经具备了小屏旗舰的身份。相信此次nubia的&小世界 大精彩&新品手机发布会,肯定会有不少我们没想到的惊喜。【微课制作必备】常用的录屏软件_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
【微课制作必备】常用的录屏软件
上传于||文档简介
&&微​课​制​作​常​用​的​录​屏​软​件​介​绍
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
你可能喜欢}

我要回帖

更多关于 录屏加录音 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信