Date: 2016-03-23

Title: m4a文件在iOS上的流媒体播放

Tags: m4a, mp4, iOS, Android

URL: m4a-streaming-play-on-mobile-phone

故障

公司项目中有个语音录制与播放的功能,QA反馈有部分 Android 机型录制的音乐文件无法在 iOS 上进行播放。看了一下 iOS 的实现代码,iOS 的实现有考虑当文件较大时先下载再播放引起的延迟,是按流形式播放的。

找到出错的 m4a 文件,发现如果按下载播放形式,不会出现任何问题;按流形式边下边播,会报错:

on-optimized formats not supported for streaming

原因

m4a 文件本质就是一个mp4文件,m4a仅是声明容器文件中仅含有音频内容。mp4和QuickTime®文件一样都是一种容器文件,类似XML那样由若干个"Atom"组成,每个 atom 文件中存放不同的meta、音频数据、视频数据、字幕等内容。而所谓 "optimize for streaming" 意指将文件中的 meta data 提到文件前部,这样播放器按流形式读取时,可以在获取音视频数据前获取具体的音视频编码信息。

mp4 和 QuickTime 可以使用 Appple 公司的 Atom Inspector 工具打开:

左边的001.m4a 文件是播放出错的 m4a 文件,可以看到,用于存入音频数据(AAC格式)的 mdata 牌ftyp 后,而存放 metadata 的 moov 处于文件的最后。

位于右边的文件是使用iTunes转换后的 m4a 文件,moov 段被移动到了文件前部,mdata 被放置于文件的最后。转换后的m4a可以正常按流形式进行播放。

解决

最初是想将文件转换放到服务端来进行,让它类似缩略图生成那样成为一种文件扩展服务。但是,考虑 CS 团队未必有时间马上开发这个扩展功能而项目又等着急用,最后我还是直接在 Android 中实现了这个 optimizing of Streaming 功能。

使用的是mp4parser Library。简单的将文件使用 mp4parser 复制一下音轨即可,因为项目中为用户录音,实际音轨只有一条,所以将那条音轨取出存入一个新文件即可。代码如下:

        Movie originalMovie = MovieCreator.build(sourceM4a);
Movie destMovie = new Movie();
Track audioTrack = originalMovie.getTracks().get(0);
destMovie.addTrack(audioTrack);
Mp4Builder builder = new DefaultMp4Builder();
Container container = builder.build(destMovie);
container.writeContainer(new FileOutputStream(destM4a).getChannel());

m4a文件在iOS上的流媒体播放的更多相关文章

  1. IOS上传文件开发

    IOS上传文件开发     在移动应用开发  文件形式上传是不可缺少的,近期把IOS这块文件上传文件代码简单的整理一下.假设大家有须要安卓这边的代码,本人也能够分享给大家! QQ群:74432915 ...

  2. 细数iOS上的那些安全防护

    细数iOS上的那些安全防护  龙磊,黑雪,蒸米 @阿里巴巴移动安全 0x00 序 随着苹果对iOS系统多年的研发,iOS上的安全防护机制也是越来越多,越来越复杂.这对于刚接触iOS安全的研究人员来说非 ...

  3. 微信双开是定时炸弹?关于非越狱iOS上微信分身高危插件ImgNaix的分析

    作者:蒸米@阿里移动安全 序言 微信作为手机上的第一大应用,有着上亿的用户.并且很多人都不只拥有一个微信帐号,有的微信账号是用于商业的,有的是用于私人的.可惜的是官方版的微信并不支持多开的功能,并且频 ...

  4. 解决protobuf不能直接在IOS上使用,利用protobuf-net在IOS上通讯

    ---------------------------------------------------------------------------------------------------- ...

  5. iOS上简单推送通知(Push Notification)的实现

    iOS上简单推送通知(Push Notification)的实现 根据这篇很好的教程(http://www.raywenderlich.com/3443/apple-push-notification ...

  6. 【转帖】ios上取得设备唯一标志的解决方案

    原文地址:http://lqzit.iteye.com/blog/2070306 注意:keychina设置完之后,项目目录里的“项目名.entitlements”文件不是手动创建出的,而是在按照如下 ...

  7. 转:基于IOS上MDM技术相关资料整理及汇总

    一.MDM相关知识: MDM (Mobile Device Management ),即移动设备管理.在21世纪的今天,数据是企业宝贵的资产,安全问题更是重中之重,在移动互联网时代,员工个人的设备接入 ...

  8. 关于iOS上的静态库

    最近再进行项目的真机调试,然后发现了一个天坑.就此研究了一些iOS上的静态库的使用: 首先我们是直接拿一个可以运行的项目来制作静态库的,网上大部分都是先创建静态库然后再写内容,看看我的方法. 1.把子 ...

  9. 阻止文件不被上传到iCloud-b

    有空用下 http://www.cocoachina.com/bbs/read.php?tid=86244 http://www.ooso.net/archives/617 http://blog.c ...

随机推荐

  1. Ubuntu下迁移MySQL数据库文件目录

    用Ubuntu的apt包管理工具安装的mysql数据库,默认将数据库文件保存在/var/lib/mysql目录下,时间久了数据库越来越大,所以准备挂载个新的硬盘专门存放mysql数据库. 1.确定my ...

  2. vsftpd配置文件丢失

    deeplinux 卸载vsftpd重装,配置文件/etc/vsftpd.conf不能自动安装,解决办法如下: apt-get remove vsftpd --purge apt-get instal ...

  3. 拦截iOS系统导航栏返回按钮事件-三种方法

    方法一:在dealloc里面书写监听事件,因为只有pop才会调用dealloc,push不会掉用 - (void)dealloc {YLLog(@"123"); } 方法二:在- ...

  4. Ajax初窥

    Ajax四个步骤 1. 创建Ajax对象2. 连接到服务器3. 发送请求4. 接收返回值 0x01 创建AJAX对象 方法1(非IE6.0) Var oAjax = new XMLHttpReques ...

  5. jsonp爬取页面

    jsonp Connection conn = Jsoup.connect("http://ip.taobao.com/service/getIpInfo.php?ip=" + i ...

  6. iscsi线缆

  7. golang http.Redirect()函数容易误解的地方

    调用http.Redirect()函数后,并不会立刻进行跳转,而是继续顺序执行函数中的所有的代码后,再进行跳转.但是Redirect后面的写界面的代码不会发送到游览器前端的. 代码如下:func Ch ...

  8. 怎样统计分析CSDN博客流量

    第一.IP.PV和UV各自是什么意思? IP.实际上也就是指独立IP,它的英文为Internet ***otocol,是独立IP数的意思.00:00-24:00同样IP地址记录一次.即使你有多台电脑. ...

  9. JavaScriptSerializer 时间格式化

    时间格式化 Model m = , Dt = DateTime.Now }; JavaScriptSerializer js = new JavaScriptSerializer(); string ...

  10. linux 提示符绝对路径

    # Turn on checkwinsize  shopt -s checkwinsize  [ "$PS1" = "\\s-\\v\\\$ " ] & ...