草庐IT

关于android:如何在视频系统中捕获和编码音频_Android

codeneng 2023-03-28 原文

How to capture and encode audio in a video system_Android

我正在尝试在 android 中构建一个开源视频系统,因为我们无法访问封闭系统中的数据。在这个系统中,我们可以修改摄像头捕获的原始数据。

我使用 MediaCodec 和 MediaMux 来完成视频数据编码和复用工作,而且效果很好。但我不知道音频部分。我使用 onFramePreview 来获取每一帧并逐帧进行编码/混合工作。但是我如何同时进行音频录制(我的意思是逐帧捕获音频,对其进行编码并将数据发送到 MediaMux)。

我做了一些研究。似乎我们使用audiorecorder来获取音频的原始数据。但是audiorecorder做一个持续的录音工作,我不认为它可以工作。

谁能给我一个提示?谢谢!


像这样创建audioRecorder:

1
2
3
4
5
6
7
8
9
10
11
12
private AudioRecord getRecorderInstance() {
    AudioRecord ar = null;
    try {
        //Get a audiorecord
        int N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);            
        ar = new AudioRecord(AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10);
    }
    catch (Exception e) {

    }
    return ar; //Returns null if mic is unavailable
}

为编码和复用准备和发送数据,像这样是单独的线程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MicrophoneInput implements Runnable {
    @Override
    public void run() {
        // Buffer for 200 milliseconds of data, e.g. 400 samples at 8kHz.
        byte[] buffer200ms = new byte[8000 / 10];

        try {
                while (recording) {
                    audioRecorder.read(buffer200ms, 0, buffer200ms.length);

                    //process buffer i.e send to encoder
                    //don't forget to set correct timestamps synchronized with video
                }
        }
        catch(Throwable x) {        
                //  
        }
    }
}

  • 谢谢你,@马龙。我已经尝试过了,但我遇到了一些麻烦。我应该把函数 audioRecord.startRecording 放在哪里?我使用回调函数 onPreviewFrame 来获取每一帧的数据并对这些数据进行编码/复用。我尝试将 startRecording 放在 onPreviewFrame 和 onPreviewFrame 之前,但两者都可以。此外,我使用 AsyncTask 进行编码背景(onPreivewFrame 逐帧调用该任务)。如果我为 audioRecord 打开另一个线程,如何为复用器提供逐帧音频?谢谢!
  • 我在 camera.startPreview() 之后有 audioRecord.startRecording。主要思想是视频被编码并发送到相机线程中的复用器。音频链存在于自己的线程中\\
    unnable 在 while{} 中循环,并在样本准备好(此处为 200 毫秒)时从 audioRecorder 读取音频样本,然后发送到编码器和复用器。 Runnable 与 audioRecord start 一起创建\\\\started: MicrophoneInput mi = new MicrophoneInput(); audioThread = 新线程(mi);
  • 再想一想:可以在 onPreviewFrame 中添加一个同步对象,以便在每个进入的视频帧上推送音频线程。因此每个视频帧都会触发音频缓冲区在单独的线程中发送到编码器。但它需要为 audioRecorder 分配更精确的缓冲区
  • 谢谢你。并感谢您解决了我的两个问题。我对如何将缓冲区从该线程发送到 onPreiewFrame 感到困惑。我们如何使它异步?我们只是让它每 200 毫秒发送一次(按时间控制)还是其他什么?你能提供更多细节吗?谢谢!
  • 您需要创建 2 个 mediacodec 实例,一个用于音频,另一个用于视频,正确配置它们。在它将数据从 onPrevieFrame 发送到 videoencoder 之后,从 MicrophoneInput 中的 run() 发送到 audioencoder。只需使用循环从 audioRecorder 获取数据并发送到编码器。性能改进的空间肯定存在。并且始终将正确的时间戳发送到编码器输入 - 多路复用器基于它进行同步
  • 根据我的理解,audioRecorder 的工作方式如下:当您要求 audioRecorder.read(buffer200ms, 0, buffer200ms.length); 时,它会填充内部线程中的内部缓冲区。它只是尝试将 200ms 从内部缓冲区复制到 buffer200ms。如果内部缓冲区中的时间少于 200 毫秒,它将返回实际复制的数据大小。分配 1 秒的缓冲区并以不那么频繁的方式进行读取可能会更好
  • 谢谢你详细说明。所以我们在run()中编写音频录制和编码函数,在onPreviewFrame中编写视频录制和编码函数。我们确保编码器的时间戳是正确的,然后我们将数据发送到 Muxer。谢谢!

有关关于android:如何在视频系统中捕获和编码音频_Android的更多相关文章

  1. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  4. ruby - 用逗号、双引号和编码解析 csv - 2

    我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

  5. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  6. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  7. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  8. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  9. ruby-on-rails - 如何在 ruby​​ 交互式 shell 中有多行? - 2

    这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式ruby​​shell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f

  10. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

随机推荐