一、标签解读

  • <audio> 标签属性

<audio id="media" src="http://www.abc.com/test.mp3" controls></audio>

src:音乐的URL (source标签在src属性不存在时使用) 
preload:预加载(none、metadata、auto。如果不使用此属性,默认为auto。)  
autoplay:自动播放 
loop:循环播放 
controls:浏览器自带的控制条

  • <video> 标签属性

        <video id="media" src="http://www.abc.com/test.mp4" controls width="400px" height="400px"> </video> 

src:视频的URL 
poster:视频封面,没有播放时显示的图片 
preload:预加载 
autoplay:自动播放 
loop:循环播放 
controls:浏览器自带的控制条 
width:视频宽度 
height:视频高度 
muted:是否输出视频的声音

二、Media对象方法和属性

  • 获取HTMLVideoElement和HTMLAudioElement对象

  1. //audio可以直接通过new创建对象

  2. Media = new Audio("http://www.abc.com/test.mp3");

  3. //audio和video都可以通过标签获取对象

  4. Media = document.getElementById("media");

  • Media方法和属性——HTMLVideoElement 和 HTMLAudioElement 均继承自 HTMLMediaElement

  1. //错误状态

  2. Media.error; //null:正常

  3. Media.error.code; //1.用户终止 2.网络错误 3.解码错误 4.URL无效

  4. //网络状态

  5. Media.currentSrc; //返回当前资源的URL

  6. Media.src = value; //返回或设置当前资源的URL

  7. Media.canPlayType(type); //是否能播放某种格式的资源

  8. Media.networkState; //0.此元素未初始化  1.正常但没有使用网络  2.正在下载数据  3.没有找到资源

  9. Media.load(); //重新加载src指定的资源

  10. Media.buffered; //返回已缓冲区域,TimeRanges

  11. Media.preload; //none:不预载 metadata:预载资源信息 auto:

  12. //准备状态

  13. Media.readyState;   //1:HAVE_NOTHING 2:HAVE_METADATA 3.HAVE_CURRENT_DATA 4.HAVE_FUTURE_DATA 5.HAVE_ENOUGH_DATA

  14. Media.seeking; //是否正在seeking

  15. //回放状态

  16. Media.currentTime = value; //当前播放的位置,赋值可改变位置

  17. Media.startTime; //一般为0,如果为流媒体或者不从0开始的资源,则不为0

  18. Media.duration; //当前资源长度 流返回无限

  19. Media.paused; //是否暂停

  20. Media.defaultPlaybackRate = value;//默认的回放速度,可以设置

  21. Media.playbackRate = value;//当前播放速度,设置后马上改变

  22. Media.played; //返回已经播放的区域,TimeRanges,关于此对象见下文

  23. Media.seekable; //返回可以seek的区域 TimeRanges

  24. Media.ended;    //是否结束

  25. Media.autoPlay; //是否自动播放

  26. Media.loop; //是否循环播放

  27. Media.play();   //播放

  28. Media.pause();  //暂停//控制

  29. Media.controls;//是否有默认控制条

  30. Media.volume = value; //音量

  31. Media.muted = value; //静音

  32. //TimeRanges(区域)对象

  33. TimeRanges.length; //区域段数

  34. TimeRanges.start(index) //第index段区域的开始位置

  35. TimeRanges.end(index) //第index段区域的结束位置

三、Media JS事件

   eventTester = function(e){  
        Media.addEventListener(e,function(){  
            console.log((newDate()).getTime(),e);  
        });  
   }  
  
   eventTester("loadstart");   //客户端开始请求数据  
   eventTester("progress");    //客户端正在请求数据  
   eventTester("suspend");     //延迟下载  
   eventTester("abort");       //客户端主动终止下载(不是因为错误引起)  
   eventTester("error");       //请求数据时遇到错误  
   eventTester("stalled");     //网速失速  
   eventTester("play");        //play()和autoplay开始播放时触发  
   eventTester("pause");       //pause()触发  
   eventTester("loadedmetadata");  //成功获取资源长度  
   eventTester("loadeddata");  //  
   eventTester("waiting");     //等待数据,并非错误    
   eventTester("playing");     //开始回放  
   eventTester("canplay");     //可以播放,但中途可能因为加载而暂停  
   eventTester("canplaythrough"); //可以播放,歌曲全部加载完毕  
   eventTester("seeking");     //寻找中  
   eventTester("seeked");      //寻找完毕  
   eventTester("timeupdate");  //播放时间改变  
   eventTester("ended");       //播放结束   
   eventTester("ratechange");  //播放速率改变  
   eventTester("durationchange");  //资源长度改变
   eventTester("volumechange");    //音量改变

事件详细说明:

四、浏览器对音视频格式支持说明

   Audio 
  Firefox:支持 Ogg Vorbis和WAV 
  Opera :支持Ogg Vorbis和WAV 
  Safari :支持MP3,AAC格式 ,和MP4 
  Chrome :支持Ogg Vorbis,MP3,WAV,AAC和MP4 
  Internet Explorer 9+ :支持MP3,AAC格式 ,和MP4 
  IOS :支持MP3,AAC格式 ,和MP4 
  Android :支持AAC和MP3 
  为了最大程度支持所有上面提到的浏览器,建议开发者使用Ogg Vorbis和MP3这两种格式例如。

<audio controls>
   <source src="myAudio.ogg" type="audio/ogg">
   <source src="myAudio.mp3" type="audio/mp3">
</audio>

   Video 
  Firefox :支持Ogg Theora格式和WEBM 
  Opera :支持Ogg Theora格式和WEBM 
  Safari :支持MP4 
  Chrome :支持Ogg Theora格式,MP4和WEBM 
  Internet Explorer 9 :支持MP4和WEBM(需要安装插件) 
  IOS :支持MP4 
  Android :支持MP4和WEBM(Android 2.3版本以上) 
   为了支持上述所有的浏览器,建议使用WebM和MP4视频文件作为source元素。例如。

<video controls>
   <source src="myVideo.mp4" type="video/mp4">
   <source src="myVideo.webm" type="video/webm">
</video>

  再来张截图示意:(http://en.wikipedia.org/wiki/Html_video_tag)

五、疑难杂症

  1、mp4格式视频无法在chrome中播放

  Chrome浏览器支持HTML5,它支持原生播放部分的MP4格式(不用通过Flash等插件)。
为什么是部分MP4呢?MP4有非常复杂的含义(见http://en.wikipedia.org/wiki/Mp4),普通人对MP4的理解是后缀为.mp4的文件。但MP4本身不是一种简单的视频格式,它是一个包装了视频和音频格式的壳。至于里面的视频和音频使用什么编码格式是可变的。MP4的视频格式可以使用DivX也可使用H264,Chrome只支持H264。
  然后,我猜测问题的原因是这样的:Chrome浏览器见到MP4后缀的文件,使用了原生HTML5视频播放起播放,但却发现视频格式无法解码。对于Firefox,它不支持原生播放MP4,于是使用了Flash,绝大部分的视频格式基本都可通过Flash播放。
  这篇2011年1月的消息提到Google将放弃对H264的支持:http://www.infoq.com/cn/news/2011/01/chrome-h264。这篇是Google方面的描述:http://blog.chromium.org/2011/01/html-video-codec-support-in-chrome.html。如果Google不再支持在Chrome上原生播放MP4,那么会调用Flash播放器播放,这样反而不会出现有些MP4文件播放不了的问题。
  为什么Chrome不支持所有的视频编码格式?绝大部份的视频编码格式都是要付版权费的,Google已经为H264买了单,Firefox没有Google那么有钱不愿意买。
  最后,我录制了一段教学视频,指导大家怎样把各种视频转换成兼容性比较好的MP4文件。视频中使用的软件是“格式工厂”(http://www.formatoz.com/CN/index.html),这个软件基本上只是做了一个界面,其核心调用了开源软件FFMPEG。由于它违反了FFMPEG的LGPL许可协议,备受指责。使用Linux的朋友可以直接使用FFMPEG命令进行视频格式转换,命令如下:
  ffmpeg -i infile.flv -vcodec libx264 o5.mp4
  如果转换出的视频在某些设备还是无法播放,可以试试利用MediaCoder转换兼容性更好的MP4

  2、让服务器能正确识别多媒体的MIME类型

  即使对浏览器来说,已经设置了正确的媒体,但有可能是您的服务器并不能正确识别多媒体的MIME类型。MIME类型告诉服务器如何处理不同的文件类型。如果你使用Apache,则可以在.htaccess文件中添加下面的音频支持:
  AddType audio/ogg ogg AddType audio/ogg oga AddType audio/wav wav AddType audio/mpeg mp3 AddType audio/mp4 mp4 AddType audio/mp4 mpa
  类似地添加如下代码,以支持视频:
  AddType video/webm webm AddType video/mp4 mp4 AddType video/ogg ogg AddType video/ogg ogv
  如果不能访问服务器的.htaccess文件,则有可能在服务器的控制面板地方有一个选项,允许查看和添加MIME类型。
  如果是Windows服务器,那么可能需要在IIS或者web.config中进行设置在web.config文件中 。

  3、文件格式转换的问题

  一种很常见的情况是,用户从客户端提交给服务端一个类型的媒体文件,并且尽管你已经从它的文件扩展名中确认了其MIME类型。但是,该文件没有被正确解码。例如,它可以是一个完全有效的MP4文件,但由于某种原因,在一些浏览器中无法播放。如果发生这种情况,最好把用户上传的文件进行编码,比如使用如Miro Video Coverter和Media Converter等编码器,可以确保正确的编码。 
  此外,一些文件,尤其是MP4文件,在测试时,不要总是在一个支持其格式的浏览器中进行测试,这是因为事实上,MP4存在不同的编码格式,可以根据不同格式对MP4(又称如H.264)进行编码(参考:http://en.wikipedia.org/wiki/H.264#Profiles)如果有的浏览器不支持其中的编码格式,那么它自然不会工作。如果遇到这种情况,尝试确保该文件是以最基本的MP4编码方式进行编码。最好建议使用工具,比如Miro转换工具,它能确保MP4文件能在最多的浏览器中得到支持。 
  如果需要支持Firefox 3.6和更低的版本,还需要转换对应的音频文件为Ogg格式},并将它们添加到中的元素中。

  4、能否在MP4完整下载前进行播放?

  一般情况下,HTML5的的音频和视频播放器将允许用户在完整下载文件前,就可以开始进行播放了,有时候,对于MP4文件来说却不能这样,要必须等待所有的视频下载完毕再播放,这主要是编码问题造成的 
  有时,MP4文件使用索引进行了编码(其中包含了比如文件长度等信息),往往这些信息是放在文件的尾部而不是头部。索引信息中,包含了文件的元信息,浏览器根据这些元信息去进行下载。如果索引放在后面的话,则必须等待到获得整个文件的索引后,才能知道文件的元信息,所以就必须等到整个文件下载完毕才能开始播放了。 
  如果您遇到这种情况,还有一个简单的修补程序,是由埃里克森Renaun提供的,下载地址为:http://renaun.com/blog/code/qtindexswapper/,下载到计算机上运行,则可以把文件的索引信息移动到文件头并保存。

  5、避免用JS访问废除的属性

  这个问题看上去好像有点多余,但每次在Stack Overflow中,都会看到很多开发者发问,比如为什么某个方法不能运行,原因在于他们使用了不存在的属性。比如,在 
<audio>和<video>标签中都有的旧的属性autobuffer,在2010年10月已经被preload取代了。 
  人们似乎忘记了,HTML5是尚未敲定的标准(虽然它的大部分内容现在已经都相当稳定),所以作为开发者,必须多到W3C的官方网站去进行查阅相关资料。

  6、Firefox 11 以上版本的音量控制的问题

  最近相信不少开发者会发现音量控制的操作在Firefox 11及以上的版本中被取消了。是的,静音和音量控制仍然是可以使用的,但要通过键盘上的上和向下键进行控制,其原因主要是发现了两个bug(请参考:http://www.iandevlin.com/blog/2012/04/html5/html5-media-controls-and-firefox),这一点请开发者注意,估计firefox会很快修复这个问题。

  7、音视频播放是否完全脱离插件?

  HTML5的音频和视频点的最大卖点之一就是不需要安装第三方插件-例如Flash 
  不幸的是,这不完全正确,ie 9及以上版本的浏览器和Safari是需要使用Microsoft Media Player和Apple的QuickTime,才能播放HTML5音频和视频。

  8、如何全屏视频?支持情况如何?

  HTML5 视频的其中一大威力在于其全屏播放的特性但HTML5 规范中,对这个居然没有任何提及,相反,在另外一个关于全屏幕播放的API中有定义,但还是在草稿阶段,在一些浏览器中开始有试验性的支持。 
  以下浏览器去一些支持全屏API,但具体使用的api方法各自有不同: 
  Chrome 19 版本以上 
  Firefox的12 + 
  Safari浏览器5.1 + 
  注:iPhone上,video自动全屏播放! 
  也有一些其他方法,能在其他浏览器中支持使用全屏API,比如https://github.com/sindresorhus/screenfull.js 
  Internet Explorer9 以上版本忽略了video poster属性 
  如果在HTML 5的video标签中使用poster属性,其含义为在视频播放前提供一张静态的图片给用户,但ie 9以上的版本,除非设置了preload属性为none,否则将会忽略掉设置的poster属性。 
  这是由于Internet Explorer是最迟支持HTML 5的浏览器,我们都习惯了其他浏览器中,如果设置了poster属性,则会在播放视频前,先显示设置的这张图片。但IE 9并不这样做,如果要播放的视频的第一帧已经加载了,则不会显示有poster属性指定的图片了,而且在IE 10中,目前依然存在这个问题。  

  9、通过HTML5技术能否访问摄像头和麦克风?

  HTML 5的起草者们,一直都希望HTML 5能访问摄像头和麦克风,因此早期是使用标签的,但现在是被getUserMedia API所取代了(详见: http://dev.w3.org/2011/webrtc/editor/getusermedia.html)。

  API本身是容易使用的 ,但目前浏览器支持相当有限。Opera是目前唯一个实现这些功能的浏览器,但只支持视频Internet Explorer 10也将对其进行部分支持,Firefox也会跟随。

  10、autoplay在iphone/ipad中不能实现的问题

  • 通过iframe

    var ifr=document.createElement("iframe");  
    ifr.setAttribute('src', "song.mp3");  
    ifr.setAttribute('width', '1px');  
    ifr.setAttribute('height', '1px');  
      
    ifr.setAttribute('scrolling', 'no');  
    ifr.style.border="0px";  
    document.body.appendChild(ifr);
  • 通过页面上的其他触摸或者点击事件来调用对应的play()方法

  11、解决iPhone中,视频自动在新窗口打开问题

HTML

<video id="player" width="480" height="320" webkit-playsinline>

Obj-C

webview.allowsInlineMediaPlayback = YES;

六、参考范例:音乐播放器

  在网上看到有人用JS写的播放器,木有仔细看,先贴过来。感觉让我自己写想不到这么周全,等后面要用再仔细寻更好方案。

  原文地址:http://www.cnblogs.com/arby/archive/2012/04/07/2436352.html

function Audio(song, playType, dom){
    /*
     * 播放器构造函数。
     * dom:为audio元素,可以不传。
     * song : 为歌曲列表,只支持数组形式,格式为[{}{}]
     * playType 为播放方式: 1 顺序播放  2 随机播放  3 单曲循环  4 全部循环
     */
    if(!dom) {
        this.media = document.createElement('audio');
        document.body.appendChild(this.media);
    }else {
        this.media = typeof dom == 'string' ? document.getElementById(dom) : dom;
    }
    this.currentIndex = 0;
    this.songList = song;
    this.countTotal = this.songList.length;
    this.playType = playType || 1;
    this.MusicInfo = [];
    this.playing = false;
}
/*
 * 播放器启动主函数
 */
Audio.prototype.startPlay = function(){
    this.media.src = this.songList[this.currentIndex].src;
    this._play();
} /*
 * 播放器播放核心函数.
 */
Audio.prototype._play = function(){
    var self = this;
    this.media.play();
    this.playing = true;
    this.mediaEvent('ended' ,callback);
    function callback(){
        //单曲循环无需单独处理,只需直接调用startPlay()函数。
 if(self.media.currentTime == self.media.duration){
            switch(self.playType){
                case 1:
                    if(self.currentIndex == self.countTotal-1){
                    return false;
                    }else{
                        self.currentIndex++;
                    }
                    break;
                case 2:
                    self.currentIndex = Math.floor(Math.random()*self.countTotal);
                    break;
                case 4: 
                    self.currentIndex++;
                    console.log("self.currentIndex==",self.currentIndex);
                    self.currentIndex = (self.currentIndex > self.countTotal-1) ? 0 : self.currentIndex;
                    break;
            }
            self.startPlay();
        }
    }
}
/*
 *播放下一首如果当前已经是最后一首则播放第一首
 */
Audio.prototype.playNext = function(){
    this.currentIndex++;
    this.currentIndex = this.currentIndex > this.countTotal-1 ? 0 : this.currentIndex;
    this.startPlay();
}
/*
 *播放上一首如果当前已经是第一首则播放最后一首
 */
Audio.prototype.playPrevious = function(){
    this.currentIndex++;
    this.currentIndex = this.currentIndex < 0 ? this.countTotal-1 : this.currentIndex;
    this.startPlay();
    
} /*
 * 暂停当前播放,如果传回调函数,则暂停后执行回调。
 */
Audio.prototype.playPause = function(callback){
    if(this.playing){
        this.media.pause();
        this.playing = false;
    }else{
        this.media.play();
        this.playing = true;
    }
    if(!callbakc){callback();}
} /*
 *  获取当前播放位置
 */
 Audio.prototype.getCurrentTime = function(){
    return this.media.currentTime;
} /*
 * 播放器各种事件监听.
 * tip 类型必须是正确的类型
 */
Audio.prototype.mediaEvent = function(eventType, callback){
    
    Event.add(this.media,eventType,callback);
} /*
 * 播放用户自定义时间,即拖动进度条。
 */
Audio.prototype.playUserTime = function(time){
    
    this.media.currentTime = time;
}
/*
 * 获取当前媒体信息
 * src 当前媒体路径
 * size 当前媒体总时长.
 */
Audio.prototype.getMusicInfo = function(){
    this.MusicInfo.src = this.media.currentSrc;
    this.MusicInfo.size = this.media.duration;
    this.MusicInfo.name = this.songList[this.currentIndex].name;
    return this.MusicInfo;
}
/*
 * 设置或者获取当前音量
 * voluems的值需大于0 小于等于 1
 */
Audio.prototype.setVolume = function(volumes){
    if(volumes) {
        this.media.volume = volumes;
    }else{
        return this.media.volume;
    }
}
/*
 * 设置或者取消静音.
 * flag的值为true是静音,false时正常
 */
Audio.prototype.muted = function(flag){
    if(flag){
        this.media.muted = 1;
    }else{
        this.media.muted = 0;
    }
}
/*
 * 向播放列表添加新歌曲
 * song为所需要添加的歌曲,可以多首,格式如构造函数中song.
 */
 Audio.prototype.addSongToList = function(song){
    this.songList.push(song);
    this.countTotal = this.songList.length;
 }
 
Audio.prototype.getBuffered = function(){
    return this.media.buffered;
}
/*全局事件监听封装函数*/
var Event = {
    add : function(node, eventType, callback){
        var node = typeof node == 'string' ? document.getElementById(node) : node;
        if(document.addEventListener){
            node.addEventListener(eventType, callback, false);
        }else{
            node.attachEvent('on' + eventType, callback);
        }
    },
    remove : function(node, eventType, callback){
        var node = typeof node == 'string' ? document.getElementById(node) : node;
        if(document.removeEventListener){
            node.removeEventListener(eventType, callback, false);
        }else{
            node.detachEvent('on' + eventType, callback);
        }
    }
} var core = { 
    formatPlayTime : function(tempTime){
        var temp = tempTime.toString().split(".")[0];
        if(tempTime<=60){
            temp = temp>=10? temp : "0"+temp;
            return "00 : " + temp;
        }else{
            var minute =Math.floor(temp/60); 
            minute = (minute >= 10)? minute : "0"+ minute;
            var second = temp%60; 
            second = (second >= 10)? second : "0"+second;
            return minute + " : " + second;
        }
    }        
}

《HTML5》 Audio/Video全解的更多相关文章

  1. [jPlayer] HTML5 Audio & Video for jQuery

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

  2. HTML5 Audio/Video 标签,属性,方法,事件汇总

    HTML5 Audio/Video 标签,属性,方法,事件汇总 (转) 2011-06-28 13:16:48   <audio> 标签属性:src:音乐的URLpreload:预加载au ...

  3. HTML5 Audio/Video 标签,属性,方法,事件汇总 (转)

    HTML5 Audio/Video 标签,属性,方法,事件   <audio> 标签属性:src:音乐的URLpreload:预加载autoplay:自动播放loop:循环播放contro ...

  4. [转帖]HTML5 Audio/Video 标签,属性,方法,事件汇总

    HTML5 Audio/Video 标签,属性,方法,事件汇总 <audio>标签属性: src:音乐的URL preload:预加载 autoplay:自动播放 loop:循环播放 co ...

  5. The jQuery HTML5 Audio / Video Library (jQuery jPlayer插件给你的站点增加视频和音频功能)

    http://jplayer.org/ The jQuery HTML5 Audio / Video Library jPlayer is the completely free and open s ...

  6. HTML5 Audio & Video 属性解析

    一.HTML 音频/视频 方法 play() play() 方法开始播放当前的音频或视频. var myVideo=document.getElementById("video1" ...

  7. [转载]HTML5 Audio/Video 标签,属性,方法,事件汇总

    <audio> 标签属性: src:音乐的URL preload:预加载 autoplay:自动播放 loop:循环播放 controls:浏览器自带的控制条 <audio id=& ...

  8. 【转载】HTML5 Audio/Video 标签,属性,方法,事件汇总

    <audio> 标签属性: src:音乐的URL preload:预加载 autoplay:自动播放 loop:循环播放 controls:浏览器自带的控制条 Html代码  <au ...

  9. html5 audio/video 的那些坑

    当我最近项目用到audio的时候,我们用到了jPlayer作为三方库. 功能实现了,暂停播放,进度条什么的,都很顺利的搞定了.后来考虑到当网速过慢时需要给播放按钮一个载入动画,然后就一发不可收拾了. ...

随机推荐

  1. 港真,到底应该选择OA还是BPM?

    越来越多企业意识到流程管理的重要性,但是,选择OA还是BPM,却让他们产生了选择困难症. 一方面,企业皆注重流程的高效运转,最好内外部的业务都能用一个系统来解决.所有流程一天就能上线什么的,那就更好啦 ...

  2. 基于AngularJs的上传控件-angular-file-upload

    今天跟大家分享的是一个依赖于angular的上传控件. 前段时间做项目遇到一个需求是上传文件,大概需要实现的样式是这样子的,见下图: 需要同时上传两个文件.并且规定文件格式和文件大小.因为前端框架使用 ...

  3. 扑面而来的碎片--图片3D炸裂效果初体验

    之前逛园子的时候看到 ChokCoco 的爆炸效果作品:[BOOM]一款有趣的Javascript动画效果 (大神英文有没有拼错呀←.←),觉得蛮有意思的,效果如下: 不过觉得这个爆炸效果还是偏软了一 ...

  4. useful commands for Kubernetes beginners

    Get pod ip and their coordinating NODE $ kubectl get pods -o wide If you want to get detailed inform ...

  5. 如何用Dockerfile创建镜像

    本文原创,原文地址为:http://www.cnblogs.com/fengzheng/p/5181222.html 创建镜像的目的 首先说DockerHub或其它一些镜像仓库已经提供了够多的镜像,有 ...

  6. 自定义ActionBar标题与菜单中的文字样式

    自定义标题文字样式 标题样式是ActionBar样式的一部分,所以要先定义ActionBar的样式 <style name="AppTheme" parent="A ...

  7. C++ std::deque

    std::deque template < class T, class Alloc = allocator > class deque; Double ended queue deque ...

  8. C# - 缓存OutputCache(二)缓存详细介绍

    本文是通过网上&个人总结的 1.缓存介绍 缓存是为了提高访问速度,而做的技术. 缓存主要有以下几类:1)客户端缓存Client Caching 2)代理缓存Proxy Caching 3)方向 ...

  9. 解析大型.NET ERP系统 业务逻辑设计与实现

    根据近几年的制造业软件开发经验,以我开发人员的理解角度,简要说明功能(Feature)是如何设计与实现的,供参考. 因架构的不同,技术实现上会有所差异,我的经验仅限定于Windows Form程序. ...

  10. 【.NET深呼吸】如何反序列化动态JSON

    .net本身除了支持SOAP.XML.二进制等序列化和反序列化,后来也加入了对JSON的序列化的支持.然而,在实际开发中,常常会遇到结构不确定的JSON对象,这些对象可能是其他代码动态生成的,你事先无 ...