当前位置: 首页 > news >正文

网站建设行业 知乎广州市官方网站

网站建设行业 知乎,广州市官方网站,泰安华航网络有限公司,aspnet网站开发工具前言 产品一直有用户反馈音频截断问题。在机遇巧合下现学现卖音频知识处理相关问题。 问题描述 我们查看以下简化播放器代码#xff1a; class AACPlayer(private val filePath: String) {private val TAG AACPlayerprivate var extractor: MediaExtractor? …前言 产品一直有用户反馈音频截断问题。在机遇巧合下现学现卖音频知识处理相关问题。 问题描述 我们查看以下简化播放器代码 class AACPlayer(private val filePath: String) {private val TAG AACPlayerprivate var extractor: MediaExtractor? nullprivate var codec: MediaCodec? nullprivate var audioTrack: AudioTrack? nullfun play() {try {extractor MediaExtractor().apply {setDataSource(filePath)}var trackIndex -1for (i in 0 until extractor!!.trackCount) {val format extractor!!.getTrackFormat(i)val mime format.getString(MediaFormat.KEY_MIME)if (mime!!.startsWith(audio/)) {trackIndex ibreak}}if (trackIndex 0) {extractor!!.selectTrack(trackIndex)val format extractor!!.getTrackFormat(trackIndex)val mime format.getString(MediaFormat.KEY_MIME)codec MediaCodec.createDecoderByType(mime!!)codec!!.configure(format, null, null, 0)codec!!.start()val sampleRate format.getInteger(MediaFormat.KEY_SAMPLE_RATE)val channelConfig if (format.getInteger(MediaFormat.KEY_CHANNEL_COUNT) 1) AudioFormat.CHANNEL_OUT_MONO else AudioFormat.CHANNEL_OUT_STEREOval bufferSize AudioTrack.getMinBufferSize(sampleRate,channelConfig,AudioFormat.ENCODING_PCM_16BIT);val audioTrackAttributes AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()val audioFormat AudioFormat.Builder().setEncoding(AudioFormat.ENCODING_PCM_16BIT).setSampleRate(sampleRate).setChannelMask(channelConfig).build()audioTrack AudioTrack.Builder().setAudioAttributes(audioTrackAttributes).setAudioFormat(audioFormat).setTransferMode(AudioTrack.MODE_STREAM).setBufferSizeInBytes(bufferSize).build()if (Build.VERSION.SDK_INT Build.VERSION_CODES.S) {logD(bufferSizeInFrames [${audioTrack?.bufferSizeInFrames}] bufferCapacityInFrames [${audioTrack?.bufferCapacityInFrames}] bufferSize [${bufferSize}] startThresholdInFrames [${audioTrack!!.startThresholdInFrames}])}audioTrack!!.play()val inputBuffers codec!!.inputBuffersval outputBuffers codec!!.outputBuffersval bufferInfo MediaCodec.BufferInfo()var isEOS falsewhile (!isEOS) {val inIndex codec!!.dequeueInputBuffer(10000)if (inIndex 0) {val buffer inputBuffers[inIndex]val sampleSize extractor!!.readSampleData(buffer, 0)if (sampleSize 0) {codec!!.queueInputBuffer(inIndex,0,0,0,MediaCodec.BUFFER_FLAG_END_OF_STREAM)isEOS true} else {val presentationTimeUs extractor!!.sampleTimecodec!!.queueInputBuffer(inIndex, 0, sampleSize, presentationTimeUs, 0)extractor!!.advance()}}var outIndex codec!!.dequeueOutputBuffer(bufferInfo, 10000)while (outIndex 0) {val outBuffer outputBuffers[outIndex]val bufferBackup outBuffer.slice()if (outBuffer.remaining() 0) {continue}//仅仅为了打印无他用val array ByteArray(bufferBackup.remaining())bufferBackup.get(array, 0, array.size)logD(array.joinToString(transform { String.format(%02x, it) }))logD(写入数据大小${array.size} hashCode ${array.contentHashCode()})audioTrack!!.write(outBuffer,outBuffer.remaining(),AudioTrack.WRITE_BLOCKING)codec!!.releaseOutputBuffer(outIndex, false)outIndex codec!!.dequeueOutputBuffer(bufferInfo, 0)}}}} catch (e: Exception) {e.printStackTrace()} finally {extractor?.release()codec?.stop()codec?.release()audioTrack?.flush()audioTrack?.stop()audioTrack?.release()}}fun logD(msg:String) {Log.d(TAG, msg)} }这也是网上充斥最多的示例代码但是上面的代码丢失尾帧的音频的问题。 getStartThresholdInFrames文档 在Android中audiotrack有一个缓冲区调用则可以阻塞或阻塞式使用audiotrack.write向里面写入数据。播放器为提高效率在缓冲大于startThresholdInFrames时取出进行播放。startThresholdInFrames一般大于等于bufferSizeInFrames。 你播放音频时不敢保证所有音频数据都是对齐startThresholdInFrames所以你会以为调用audiotrack.flush可以解决问题了。但是我们阅读相关文档flush文档发现这个API只是丢弃之前的数据加速audiotrack.write。 解决方案 在音频流写入结束调用audiotrack.stop 这个函数会将未播放的数据进行加载播放在结束。audiotrack.stop文档 在上述的代码我们如下编写 class AACPlayer(...) {//...fun play() {try {while (outIndex 0) {//....略//结束调用stop刷出残余音频if (bufferInfo.size 0 (bufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM) ! 0) {audioTrack!!.stop()break}//....略}}catch(...){//...}finally{} finally {extractor?.release()codec?.stop()codec?.release()audioTrack?.flush()//注释多余的stop//audioTrack?.stop()audioTrack?.release()}} } 当然你如果比较骚可以进行补帧操作 class AACPlayer(...) {//...fun play() {try {while (outIndex 0) {//....略if (bufferInfo.size 0 (bufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM) ! 0) {var interpolationFrame (audioTrack!!.startThresholdInFrames / bufferSize) 1while (interpolationFrame 0) {interpolationFrame--;audioTrack!!.write(ByteArray(bufferSize), 0, bufferSize)}break}//....略}}catch(...){//...}finally{} finally {//略}} } 实践 我们有一个极短音频且有效音在末尾那么在部分手机上将无法听到这个音频 在某手机上相关输出参数如下 bufferSizeInFrames [11310] bufferCapacityInFrames [11310] bufferSize [45240] startThresholdInFrames [11310]这个文件对应的PCM数据40960(A000h)字节大小。 我们看下这个文件的末端可以看到很多有效数据。 我们在看看文件最前面PCM数据 全是空数据。 所以这个文件只有末尾才音频。 我们算一下Audiotrack刷新次数 文件PCM大小/Audiotrack刷新阈值 40960/11310 3.6假设如果我们有效音频在最后0.6将无法播放
http://www.zqtcl.cn/news/117063/

相关文章:

  • 快速搭建网站视频教程看想看的做想做的电影网站好
  • 网站聊天怎么做2345网址导航智能主版
  • 如何优化网站加载速度做推广公司
  • 网站下载不了视频php网站 数据库链接
  • 制作网页网站教程wordpress建立扁平化
  • 网站建设小知识郑州网站建设找伟置
  • 苏中建设官方网站旅游做攻略用什么网站好
  • 信息门户网站制作wordpress改商城
  • 企业类网站有哪些甘肃省和住房建设厅网站
  • 嘉兴市住房和城乡建设局网站wordpress nodejs版本
  • 做网站 百度推广深圳外贸招聘
  • 网站留言板功能网站建设 核对流程
  • WordPress输出当前网址郑州官网seo厂家
  • c 网站开发框架wordpress建站的教程
  • 营销 推广 网站王烨演的电视剧
  • 阳泉营销型网站建设网站360做的标记如何取消
  • win7 iis asp网站配置文件注册建设网站的公司网站
  • 品牌网站建设预算网站制作过程内容
  • 石河子建设网站网站开发参考资料
  • 网站开发招标参数wordpress个性化友情链接页面
  • 建设企业网站有哪些wordpress进入中国市场
  • 大学社团网站建设虚拟主机如何做网站
  • 销售的产品是帮别人做网站电脑搭建网站
  • h5商城网站是什么莆田网站建设技术托管
  • 优惠券怎么做自己的网站英文网站怎么设计
  • 做网站怎么样才能排在首页做微网站的公司哪家好呢
  • 分析网站外链分析工具wordpress同步简书
  • 电子商务网站案例分析互动游戏制作软件
  • 网站做子域名做美团旅游网站多少钱
  • php做网站架构图开家做网站公司有哪些