打算用audio自己做个播放器,需要用audio标签的currentTime属性,来控制播放进度。但是这个属性在FireFox及ie11下都有效,但就是在chrome下面,设置了无效,不知道各位大神知道原因吗?
代码如下:
.directive('mediaPlayer',function(mediaPlayerConfig,$interval,$timeout){ return { restrict:'EA', templateUrl:'template/player.html', scope:{ playList:'=' }, controller:function($scope){ var player=this; var conf=mediaPlayerConfig; var playList=$scope.playList||[]; var $audio,isPlaying=false; var timer=null; var index=0; var audioLike={ currentTime:0, duration:0, volume:0 }; player.initialize=function(){ $scope.audioLike=audioLike; audioLike.volume=$audio.volume; player.play(index) }; player.setAudio=function(element){ $audio=element[0]; player._bindEvents(element); }; player.play=function(file){ var idx; if(angular.isNumber(file)){ idx=file; file=playList[idx]; } if(file){ $audio.src=file[conf.fileUrlProp]; $scope.currentFile=file; } $interval.cancel(timer); timer=$interval(function(){ audioLike.currentTime=$audio.currentTime.toFixed(0); },1000); $audio.play(); isPlaying=true; }; player.pause=function(){ $audio.pause(); isPlaying=false; $interval.cancel(timer); }; //播放上一首,如果已经是第一首,则跳到最后一首 player.prev=function(){ index=index===0? playList.length-1: index-1; player.play(index); }; //播放下一首,如果已经是最后一首,则跳到第一首 player.next=function(){ index=index===(playList.length-1)? 0: index+1; player.play(index); }; player.skipTo=function(sec){ $audio.currentTime=sec; }; player.togglePlay=function(){ var method=isPlaying?'pause':'play'; player[method](); }; player.isPlay=function(){ return isPlaying; }; player.random=function(){ var min=0; var max=playList.length-1; var range=max-min; var rand=Math.random(); rand=min + Math.round(rand * range); player.play(rand); }; player._bindEvents=function(element){ element .on('canplay',function(e){ $scope.$apply(function(){ audioLike.duration=$audio.duration.toFixed(0); }); }) .on('ended',function(){ //如果允许循环 if(conf.loop){ } if(conf.random){ player.random(); return; } $scope.$apply(function(){ player.next(); }); }) .on('progress',function(e){ console.log(e); }); }; player.volume=function(volume){ if(angular.isNumber(volume)){ $audio.volume=volume; }else{ return $audio.volume; } }; }, link:function(scope,element,attr,mediaPlayerCtrl){ mediaPlayerCtrl.initialize(); scope.skipTo=function(){ mediaPlayerCtrl.skipTo(250); }; } } })
刚正好遇到这个问题,错误发生在idea自带server在播放本地音频,soundmanager setPosition时自动归零。
经验证是和response header有关的。我通过对MP3资源set不同的response header
来验证,结果如下(貌似segmentfault不支持markdown的表格,所以下面排版有点乱。):
ieContent-Type
必须,当我设为audio/mpeg
时才能播放,设为application/octet-stream
不能。Content-Length
必须。和Accept-Ranges
无关。
chromeContent-Type
无关,设为application/octet-stream
可以播放。Content-Length
,Accept-Ranges
必须都有才可更改 currentTime。
也就是说ie需要response header 有正确的Content-Type
,Content-Length
。
chrome需要头部有Content-Length
和Accept-Ranges
。(Firefox没测)
还有,MDN上的Configuring servers for Ogg media中有更详细的描述:
Handle HTTP 1.1 byte range requests correctly
In order to support seeking and playing back regions of the media that aren't yet downloaded, Gecko uses HTTP 1.1 byte-range requests to retrieve the media from the seek target position. In addition, Gecko uses byte-range requests to seek to the end of the media (assuming you serve the Content-Length header) in order to determine the duration of the media.
Your server should accept the Accept-Ranges: bytes HTTP header if it can accept byte-range requests. It must return 206: Partial content to all byte range requests; otherwise, browsers can't be sure you actually support byte range requests.
Your server must also return "206: Partial Content" for the request "Range: bytes=0-" as well.
...
以上,
第一次在segmentfault回答问题,如有错漏,欢迎指正。
请问你解决这个问题了吗?我尝试了很多办法,没找到原因。但是发现可能跟router有关,我用的symfony框架,如果是简单的本地文件不会出现这种情况,一到symfony体系里面就不行,求解
多谢用户just_do_it_5811fcecc2979的提示,我发现这个问题确实是和服务器有关的。
具体来说,我用Intellij IDEA自带的服务器时(即IDEA直接打开html文件,鼠标移到编辑器的右上区域,出现一个有若干浏览器图标的横条,点击chrome图标,会使用idea自带的文件服务器用chrome打开,端口是63342),在chrome下拖动进度条也会出现跳到开头0S重新播放的问题,用IE11却正常。
然后我试了另外一个hfs服务器(Http file server,是一个软件,并不是tomcat apache nginx之类的一个新的服务器,正好有这个软件顺便试一下),chrome下拖动完全正常。所以猜测原因是和服务器有关,具体来说可能是下载mp3文件时的http response header有关。下面是以上两种服务器的response header:
【IDEA自带服务器】
HTTP/1.1 200 OK Content-Type: audio/mpeg server: IntelliJ IDEA 14.1.7 date: Thu, 02 Feb 2017 12:03:10 GMT X-Frame-Options: SameOrigin X-Content-Type-Options: nosniff x-xss-protection: 1; mode=block cache-control: private, must-revalidate last-modified: Sat, 28 Jan 2017 14:37:02 GMT content-length: 3694385
【hfs服务器】
HTTP/1.1 200 OK Content-Type: application/octet-stream Content-Length: 3694385 Accept-Ranges: bytes Server: HFS 2.3d Last-Modified: Sat, 28 Jan 2017 14:37:02 GMT Content-Disposition: attachment; filename="%CB%B3%C1%F7%B6%F8%CF%C2 - %D5%C5%F6%A6%D3%B1 %CD%F2%BC%D2%C3%FA.mp3";
一会儿再试一下tomcat和nginx。后面有发现的话再更新这个答案。