webrtc视频录制

  • html
<html>
    <head>
        <title>WebRTC capture video and audio</title>

        <link rel="stylesheet" href="css/main.css"/>

        <style>
            .none {
                -webkit-filter: none;   
            }

            .blur {
                -webkit-filter: blur(3px);  
            }

            .grayscale {
                -webkit-filter: grayscale(1);   
            }

            .invert {
                -webkit-filter: invert(1);  
            }

            .sepia {
                -webkit-filter: sepia(1);
            }

        </style>
    </head>

    <body>
        <section>
        <div>
            <label>audio Source:</label>
            <select id="audioSource"></select>
        </div>

        <div>
            <label>audio Output:</label>
            <select id="audioOutput"></select>
        </div>

        <div>
            <label>video Source:</label>
            <select id="videoSource"></select>
        </div>

        <div>
            <label>Connect Server:</label>
            <button id="connect">Connect</button>
            <label>Room Name: </label>
            <input type="text" id="room" value="aaa"></input>
        </div>
        <div>
            <button id="leave" disabled>Leave</button>
        </div>
        </section>
        <section>
        <div>
            <label>Filter:</label>
            <select id="filter">
                <option value="none">None</option>
                <option value="blur">blur</option>
                <option value="grayscale">Grayscale</option>
                <option value="invert">Invert</option>
                <option value="sepia">sepia</option>
            </select>
        </div>

            <!--<audio autoplay controls id='audioplayer'></audio>-->
        <table>
            <tr>
                <td><video autoplay playsinline id="player"></video></td>
                <td><video playsinline id="recplayer"></video></td>
                <td><div id='constraints' class='output'></div></td>
            </tr>
            <tr>
                <td><button id="record">Start Record</button></td>
                <td><button id="recplay" disabled>Play</button></td>
                <td><button id="download" disabled>Download</button></td>
            </tr>
        </table>

        </section>
        <section>
        <div>
            <button id="snapshot">Take snapshot</button>
        </div>
        <div>
            <canvas id="picture"></canvas>
        </div>
        </section>

        <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
        <script src="./js/client.js"></script>
    </body>
</html>


客户端js

'use strict'

//devices
var audioSource = document.querySelector('select#audioSource');
var audioOutput = document.querySelector('select#audioOutput');
var videoSource = document.querySelector('select#videoSource');

//filter
var filtersSelect = document.querySelector('select#filter');

//picture
var snapshot = document.querySelector('button#snapshot');
var picture = document.querySelector('canvas#picture');
picture.width = 640;
picture.height = 480;

var videoplay = document.querySelector('video#player');
//var audioplay = document.querySelector('audio#audioplayer');

//div
var divConstraints = document.querySelector('div#constraints');

//record
var recvideo = document.querySelector('video#recplayer');
var btnRecord = document.querySelector('button#record');
var btnPlay = document.querySelector('button#recplay');
var btnDownload = document.querySelector('button#download');

var buffer;
var mediaRecorder;

//socket.io
var btnConnect = document.querySelector('button#connect');
var btnLeave = document.querySelector('button#leave');
var inputRoom = document.querySelector('input#room');

var socket;
var room;

function gotDevices(deviceInfos){

    deviceInfos.forEach(function(deviceinfo){

        var option = document.createElement('option');
        option.text = deviceinfo.label;
        option.value = deviceinfo.deviceId;
    
        if(deviceinfo.kind === 'audioinput'){
            audioSource.appendChild(option);
        }else if(deviceinfo.kind === 'audiooutput'){
            audioOutput.appendChild(option);
        }else if(deviceinfo.kind === 'videoinput'){
            videoSource.appendChild(option);
        }
    })
}

function gotMediaStream(stream){

    var videoTrack = stream.getVideoTracks()[0];
    var videoConstraints = videoTrack.getSettings();
    
    divConstraints.textContent = JSON.stringify(videoConstraints, null, 2);

    window.stream = stream;
    videoplay.srcObject = stream;

    //audioplay.srcObject = stream;
    return navigator.mediaDevices.enumerateDevices();
}

function handleError(err){
    console.log('getUserMedia error:', err);
}

function start() {

    if(!navigator.mediaDevices ||
        !navigator.mediaDevices.getUserMedia){

        console.log('getUserMedia is not supported!');
        return;

    }else{

        var deviceId = videoSource.value; 
        var constraints = {
            video : {
                width: 640, 
                height: 480,
                frameRate:15,
                facingMode: 'environment',
                deviceId : deviceId ? {exact:deviceId} : undefined 
            }, 
            audio : false 
        }

        navigator.mediaDevices.getUserMedia(constraints)
            .then(gotMediaStream)
            .then(gotDevices)
            .catch(handleError);
    }
}

start();

videoSource.onchange = start;

filtersSelect.onchange = function(){
    videoplay.className = filtersSelect.value;
}

snapshot.onclick = function() {
    picture.className = filtersSelect.value;
    picture.getContext('2d').drawImage(videoplay, 0, 0, picture.width, picture.height);
}

function handleDataAvailable(e){
    if(e && e.data && e.data.size > 0){
        buffer.push(e.data);            
    }
}

function startRecord(){
    
    buffer = [];

    var options = {
        mimeType: 'video/webm;codecs=vp8'
    }

    if(!MediaRecorder.isTypeSupported(options.mimeType)){
        console.error(`${options.mimeType} is not supported!`);
        return; 
    }

    try{
        mediaRecorder = new MediaRecorder(window.stream, options);
    }catch(e){
        console.error('Failed to create MediaRecorder:', e);
        return; 
    }

    mediaRecorder.ondataavailable = handleDataAvailable;
    mediaRecorder.start(10);

}

function stopRecord(){
    mediaRecorder.stop();
}

btnRecord.onclick = ()=>{

    if(btnRecord.textContent === 'Start Record'){
        startRecord();  
        btnRecord.textContent = 'Stop Record';
        btnPlay.disabled = true;
        btnDownload.disabled = true;
    }else{
    
        stopRecord();
        btnRecord.textContent = 'Start Record';
        btnPlay.disabled = false;
        btnDownload.disabled = false;

    }
}

btnPlay.onclick = ()=> {
    var blob = new Blob(buffer, {type: 'video/webm'});
    recvideo.src = window.URL.createObjectURL(blob);
    recvideo.srcObject = null;
    recvideo.controls = true;
    recvideo.play();
}

btnDownload.onclick = ()=> {
    var blob = new Blob(buffer, {type: 'video/webm'});
    var url = window.URL.createObjectURL(blob);
    var a = document.createElement('a');

    a.href = url;
    a.style.display = 'none';
    a.download = 'aaa.webm';
    a.click();
}

function connectServer(){

    socket = io.connect();

    btnLeave.disabled = false;
    btnConnect.disabled = true;

    ///////
    socket.on('joined', function(room, id){
        console.log('The User(' + id + ') have joined into ' + room);   
    });

    socket.on('leaved', function(room, id){ 
        console.log('The User(' + id + ') have leaved from ' + room);
    });

    //join room
    room = inputRoom.value;
    if(room !== ''){
        socket.emit('join', room);  
    }

}

btnConnect.onclick = ()=> {
    connectServer();
}

btnLeave.onclick = ()=> {
    if(room !== ''){
        socket.emit('leave', room);
        btnLeave.disabled = true;
        btnConnect.disabled = false;
        socket.disconnect(); 
    }
}


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

推荐阅读更多精彩内容