Html5 音视频

音视频基础知识

  • 简单理解
    - 视频:连续的画面,特定格式编码,媒体流形式
    - 音频:特定格式编码,媒体流形式

  • 格式
    - 视频:mp4、ogv、webm
    - 音频:mp3、ogg、wav

video/audio 标签及常用属性

poster:视频播放前的封面,音频不存在该属性
preload="auto/meta/none":规定是否在页面加载后载入音频。如果设置了 autoplay 属性,则忽略该属性
autoplay:自动播放
controls:控制台
loop:循环播放
source:资源标签
206 Partial Content

加载本地文件,速度快
    <video src="../echowo.mp4" width="640px" autoplay controls/>
      您的浏览器不支持video标签。
    </video>

加载网络视频,速度慢
    <video src="http://video.echowo.com/mk.mp4" width="640px" autoplay controls/>
      您的浏览器不支持video标签。
    </video>

加载不存在的视频
    <video src="http://www.echowo.com/notexist.mp4" autoplay controls/>
      您的浏览器不支持video标签。
    </video>

视频属性详解(兼容浏览器)
    <video id="myVideo" controls width="640px" poster="../poster.jpg" />
      <source src="http://video.echowo.com/mk.mp4" type="video/mp4" />
      <source src="../echowo.mp4" type="video/mp4" />
      <source src="http://www.echowo.com/notexist.mp4" type="video/mp4" />
      <source src="http://video.echowo.com/mk.mp4" type="video/mp4" />
      您的浏览器不支持video标签。
    </video>

加载本地文件,速度快
    <audio src="../echowo.wav" autoplay controls/>
      您的浏览器不支持audio标签。
    </audio>

加载不存在的音频
    <audio src="http://www.echowo.com/notexist.mp3" autoplay controls/>
      您的浏览器不支持audio标签。
    </audio>

音频属性详解 
    <audio id="myAudio" controls />
      <source src="../echowo.mp3" type="audio/mp3" />
      <source src="../echowo.ogg" type="audio/ogg" />
      <source src="../echowo.wav" type="audio/wav" />
      您的浏览器不支持audio标签。
    </audio>

video/audio API事件

  • loadstart
    开始加载视频的元数据
  • durationchange
    时长改变事件
  • loadedmetadata *
    元数据被加载事件(作初始化工作)
  • progress *
    获取媒介数据事件(请求视频数据)
  • suspend
    在媒介数据完全加载之前不论何种原因终止取回媒介数据事件(有数据需要延时下载的事件)
  • loadeddata
    媒介数据已加载事件
  • canplay *
    文件就绪可以开始播放
  • canplaythrough *
    能够无需因缓冲而停止即可播放至结尾事件

点击播放时触发以下事件

  • play
    开始播放事件
  • playing
    视频正在播放中
  • timeupdate *
    播放位置改变事件

暂停时触发

  • pause
    暂停事件

音量改变触发

  • volumechange *
    音量改变事件

视频进度条改变时触发

  • seeking *
    定位活动事件
  • timeupdate
    播放位置改变事件
  • seeked
    定位完成事件
  • waiting *
    已停止播放但打算继续播放时触发事件(网络播放时下一帧流数据还未到来时触发缓冲)
  • ended *
    已播放到最后事件
<video src="../echowo.mp4" width="640px" autoplay controls/>
      您的浏览器不支持video标签。
</video>
<script type="text/javascript">
  ["loadstart", "progress", "suspend", "abort", "emptied", 
    "stalled", "loadedmetadata", "loadeddata", "canplaythrough", 
    "playing", "waiting", "seeking", "ended", "durationchange", 
    "timeupdate", "play", "seeked", "ratechange", "volumechange",
     "pause", "error", "canplay"]
    .forEach(function(item) {
        v["on" + item] = function(e) {
          console.log(item, e);
        };
</script>

video/audio API属性

  • currentSrc *
    当前视频播放地址
  • duration *
    视频总时长
  • currentTime *
    当前播放的倍速
  • volume *
    当前音量
  • buffered *
    当前缓冲量
  • paused *
    是否暂停
  • ended *
    是否结束
  • muted *
    是否静音
  • playbackRate *
    当前播放的倍速
    <video id="myVideo" width="640px" controls/>
      <!--<source src="http://video.mukewang.com/mk.mp4" type="video/mp4" />-->
      <source src="../imooc.mp4" type="video/mp4" />
      <source src="../imooc.webm" type="video/webm" />
      <source src="../imooc.ogv" type="video/ogv" />
      您的浏览器不支持video标签。
    </video>
    <button id="play">播放</button>
    <button id="pause">暂停</button>
    <script>
      <!-- 常用属性 -->
      var v = document.getElementById('myVideo');
      var playBtn = document.getElementById('play');
      var pauseBtn = document.getElementById('pause');
      v.onloadedmetadata = function() {
        console.log("当前视频播放地址:" + v.currentSrc);
        console.log("视频总时长:" + v.duration);
        console.log("当前播放的倍速:" + v.playbackRate);
        console.log("是否暂停:" + v.paused);
        console.log("是否结束:" + v.ended);
        console.log("是否静音:" + v.muted);
      }
      v.ontimeupdate = function() {
        console.log("当前播放时间:" + v.currentTime);
        console.log("当前缓冲量:" + v.buffered.end(0));
      }
      v.on = function() {
        console.log("当前音量:" + v.volume);
      }
      playBtn.onclick = function() {
        v.play();
      }
      pauseBtn.onclick = function() {
        v.pause();
      }

自定义视频播放器

图标可以去 www.iconfont.cn 那边下载一整套阿里的图标

<link href="css/style.css" rel="stylesheet" />
<script src="js/jquery.min.js"></script>

<div class="vContainer">
      <video id="myVideo">
      <source src="../echoswo.mp4" type="video/mp4">
      <source src="../echoswo.ogv" type="video/ogv">
      <source src="../echoswo.webm" type="video/webm">
      
      </video>
      <div class="caption">自定义视频播放器</div>
      <div class="control">
            
      </div>
</div>
    <div class="vContainer">
      <!-- 视频元素 -->
      <video id="myVideo" preload="metadata"/>
        <source src="../echoswo.mp4" type="video/mp4" />
        <source src="../echoswo.webm" type="video/webm" />
        <source src="../echoswo.ogv" type="video/ogv" />
        您浏览器不支持视频播放,请更换浏览器
      </video>
      <!-- 标题 -->
      <div class="caption">自定义视频播放器</div>
      <!-- 控制区 -->
      <div class="control">
        <!-- 控制区 上面区域 进度条和时间 -->
        <div class="top">
          <div class="progress">
            <span class="timeBar"></span>
          </div>
          <div class="time">
            <span id="currentTime">00:00</span>
            <span>/</span>
            <span id="duration">00:00</span>
          </div>
        </div>
        <!-- 控制区 下面区域 按钮 -->
        <div class="bottom">
          <div class="button play" id="playBtn"></div>
          <div class="button stop" id="stopBtn"></div>
          <div class="button text selected" id="speed1Btn">x1</div>
          <div class="button text" id="speed3Btn">x3</div>
          <div class="volume">
            <span class="volumeBar"></span>
          </div>
          <div class="button sound" id="soundBtn"></div>
        </div>
      </div>
      <!-- loading -->
      <div class="loading"></div>
    </div>

<script src="js/script.js"></script>
  • style.css
body {
  margin: 0px;
  padding: 0px;
}
/* 视频容器 */
.vContainer {
  width: 640px;
    height: 360px;
  margin: 30px auto;
    position: relative;
    overflow: hidden;
    background-color: #DEDEDE;
}
/* 标题 */
.caption {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    padding: 10px;
    font-size: 20px;
    font-weight: bold;
  color: #CCCCCC;
  background-color: #1F1F1F;
  z-index: 1;
}
/* 控制区域 */
.control {
  position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
  color: #CCCCCC;
  background-color: #1F1F1F;
    z-index: 1;
}
/* 控制区 上部分 */
.control .top {
  height: 11px;
    border-bottom: 1px solid #404040;
    padding: 1px 5px;
    background: #1F1F1F;
}
/* 控制区 上部分 进度条 */
.control .top .progress {
  width: 85%;
    height: 10px;
    position: relative;
    float: left;
    cursor: pointer;
    background: #404040;
  border-radius: 5px;
}
.control .top .progress .timeBar {
  height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    display: block;
    border-radius: 5px;
}
/* 控制区 上部分 进度条 时间条 */
.control .top .progress .timeBar {
    z-index: 3;
    width: 0px;
    background: #F9D43A;
}
/* 控制区 上部分 时间 */
.control .top .time {
    width: 15%;
  float: right;
    text-align: center;
    font-size: 0px;
    line-height: 12px;
}
.control .top .time span {
  font-size: 11px;
}
/* 控制区 下部分 */
.control .bottom {
  clear: both;
    background: #1F1F1F;
}
/* 控制区 统一处理button样式 */
.control .button {
    float: left;
    width: 32px;
    height: 32px;
    padding: 0 5px;
    cursor: pointer;
}
/* 控制区 按钮图标 */
.control .bottom .play {
    background: url("play.png") no-repeat 7px 2px;
}
.control .bottom .pause {
    background: url("pause.png") no-repeat 7px 2px;
}
.control .bottom .stop {
    background: url("stop.png") no-repeat 7px 2px;
}
.control .bottom .sound {
    background: url("sound.png") no-repeat 7px 2px;
}
.control .bottom .mute {
    background: url("mute.png") no-repeat 7px 2px;
}
.control .bottom .text {
    font-size: 16px;
    font-weight: bold;
    line-height: 32px;
    text-align: center;
    color: #777777;
}
.control .bottom .selected {
  color: #FFFFFF;
}
.control .bottom .sound,
.control .bottom .mute {
  float: right;
}
/* 控制区 声音条 */
.control .bottom .volume {
    position: relative;
    cursor: pointer;
  float: right;
    width: 70px;
    height: 10px;
    margin-top: 10px;
    margin-right: 10px;
  background-color: #404040;
}
.control .bottom .volumeBar {
    display: block;
  width: 0px;
    height: 100%;
    position: absolute;
    top: 0px;
    left: 0px;
    background-color: #EEEEEE;
    z-index: 2;
}
/* loading */
.loading {
  position: absolute;
  width: 54px;
  height: 55px;
  left: 50%;
  top: 50%;
  margin-left: -27px;
  margin-top: -27px;
  z-index: 1;
  background: url("../image/loading.gif") no-repeat 0px 0px;
}

  • script.js

(function($) {
  
  // 获取video元素
  var video = $('#myVideo');
  console.log(video);
  console.log(video[0]);
    var timeFormat = function(seconds) {
        var minite = Math.floor(seconds / 60);
    if(minite < 10) {
      minite = "0" + minite;
    }
        var second = Math.floor(seconds % 60);
    if(second < 10) {
      second = "0" + second;
    }
        return minite + ":" + second;
    };
  
  // 标题和控制板显示/隐藏
  var showTitleAndControl = function(shouldShow) {
    if(shouldShow) {
      $('.control').stop().animate({'bottom':0}, 500);
            $('.caption').stop().animate({'top':0}, 500);
    } else {
      $('.control').stop().animate({'bottom':-50}, 500);
      $('.caption').stop().animate({'top':-50}, 500);
    }
  }
  
  // 播放和暂停切换
  var playAndPause = function() {
    if(video[0].paused || video[0].ended) {
            $('#playBtn').removeClass('play').addClass('pause');
            video[0].play();
        }
        else {
            $('#playBtn').removeClass('pause').addClass('play');
            video[0].pause();
        }
  }
  
  // 结束视频
  var stopVideo = function() {
        video[0].pause();
    updateProgress($('.progress').offset().left);
    $('#playBtn').removeClass("pause").addClass("play");
  }
  
  // 调整播放速度
  var playSpeed = function(speed) {
    if(speed == 1) {
      $('#speed1Btn').addClass("selected");
      $('#speed3Btn').removeClass("selected");
    } else if(speed == 3) {
      $('#speed1Btn').removeClass("selected");
      $('#speed3Btn').addClass("selected");
    }
    video[0].playbackRate = speed;
  }
  
  // 声音和静音切换
  var soundAndMute = function() {
    if(video[0].muted) {
      video[0].muted = false;
      $('#soundBtn').removeClass("mute").addClass("sound");
      $('.volumeBar').css('width', video[0].volume * 100 + '%');
    } else {
      video[0].muted = true;
      $('#soundBtn').removeClass("sound").addClass("mute");
      $('.volumeBar').css('width', 0);
    }
    };
  
  // 进度拖拽处理
  var enableProgressDrag = function() {
    var progressDrag = false;
    $('.progress').on('mousedown', function(e) {
      progressDrag = true;
      updateProgress(e.pageX);
    });
    $(document).on('mouseup', function(e) {
      if(progressDrag) {
        progressDrag = false;
        updateProgress(e.pageX);
      }
    });
    $(document).on('mousemove', function(e) {
      if(progressDrag) {
        updateProgress(e.pageX);
      }
    });
  };
  // 更新进度
  var updateProgress = function(x) {
    var progress = $('.progress');
    
    var position = x - progress.offset().left;
    var percentage = 100 * position / progress.width();
    if(percentage > 100) {
      percentage = 100;
    }
    if(percentage < 0) {
      percentage = 0;
    }
    $('.timeBar').css('width', percentage+'%');
    
    video[0].currentTime = video[0].duration * percentage / 100;
  };
  
  // 声音拖拽处理
  var enableSoundDrag = function() {
    var volumeDrag = false;
    $('.volume').on('mousedown', function(e) {
      volumeDrag = true;
      updateVolume(e.pageX);
      video[0].muted = false;
      $('#soundBtn').removeClass("mute").addClass("sound");
    });
    $(document).on('mouseup', function(e) {
      if(volumeDrag) {
        volumeDrag = false;
        updateVolume(e.pageX);
      }
    });
    $(document).on('mousemove', function(e) {
      if(volumeDrag) {
        updateVolume(e.pageX);
      }
    });
  };
  // 更新声音
  var updateVolume = function(x, vol) {
        var volume = $('.volume');
        var percentage;
    // 如果设置了vol参数,则直接使用vol
        if(vol) {
            percentage = vol * 100;
        } else {
            var position = x - volume.offset().left;
            percentage = 100 * position / volume.width();
        }
        if(percentage > 100) {
            percentage = 100;
        }
        if(percentage < 0) {
            percentage = 0;
        }
        $('.volumeBar').css('width', percentage + '%');
    
        video[0].volume = percentage / 100;
    };
  
  // 获取元数据,初始化视频数据
  video.on("loadedmetadata", function() {
  
    video.width($('.vContainer').width());
    video.height($('.vContainer').height());
    
    showTitleAndControl(false);
    
    $('#currentTime').text(timeFormat(0));
        $('#duration').text(timeFormat(video[0].duration));
        
    // 鼠标进入视频区域时,显示标题和控制板
    // 鼠标离开视频区域时,隐藏标题和控制板
    $('.vContainer').hover(function() {
            showTitleAndControl(true);
        }, function() {
            showTitleAndControl(false);
        })
    
    // 播放按钮事件绑定
    $('#playBtn').on('click', playAndPause);
    // 结束按钮事件绑定
    $('#stopBtn').on('click', stopVideo);
    // 1倍速度按钮事件绑定
    $('#speed1Btn').on('click', function() {
      playSpeed(1);
    });
    // 3倍速度按钮事件绑定
    $('#speed3Btn').on('click', function() {
      playSpeed(3);
    });
    // 声音按钮事件绑定
    $('#soundBtn').on('click', soundAndMute);
    // 进度条拖拽事件绑定
    enableProgressDrag();
    // 声音条拖拽事件绑定
    enableSoundDrag();
    
    // 初始化声音
    updateVolume(0, 0.7);
  });
  
  var loadingTimer = null;
  // 每一次播放位置发生改变
  video.on('timeupdate', function() {
        var currentTime = video[0].currentTime;
        var duration = video[0].duration;
        var percent = 100 * currentTime / duration;
        $('.timeBar').css('width', percent + '%');
        $('#currentTime').text(timeFormat(currentTime));
    
    $('.loading').fadeOut(100);
    clearTimeout(loadingTimer);
    loadingTimer = setTimeout(function() {
      if(!video[0].paused && !video[0].ended) {
        $('.loading').fadeIn(100);
      }
    }, 500);
    });
  
  // 视频播放结束的时候
  video.on('ended', function() {
    updateProgress($('.progress').offset().left);
    $('#playBtn').removeClass("pause").addClass("play");
  });
  
  // 可以播放视频的时候
  video.on('canplay', function() {
    $('.loading').fadeOut(100);
  });
  
})(jQuery);

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容