ツールを使わずにハングアウトを録画する(未完成)

ツールを使わずにハングアウトを録画する

ツールを使わずにYoutubeを録画する

ハングアウトを気軽に録画できたら便利だなーとおもって、興味本位で調べ始めたら惜しいところまで来たので備忘録。

まだ、この記事の方法だけだと、未完成ですがサイトに埋め込まれているcampasタグやvideoタグを外部からの操作で録画できるのはちょっと便利な気がする。

ちなみに、ブックマークレットというブックマークにJavascriptを登録する機能を使っています。

前提

動作検証した環境です。

Chrome:69.0.3497.100(現時点の最新)

ブックマークレットとは

ブックマークレットとは、ブラウザのブックマークにURLの代わりにスクリプトを登録しておき、実行したページに対して簡単な処理を実行させる仕組みのことです。

例えば、下記スクリプトを保存しておけば、aタグに設定されているURL一覧を取得できます。

javascript: var a = document.getElementsByTagName("a");var urls = "";for (var i = 0; i < a.length; i++) urls = urls + "\n" + a[i].href;alert(urls);

実行結果


このブックマークレットを利用することで、動画保存用のスクリプトを実行することができます。

準備

準備の方法を順を追って説明します。

ブックマーク マネージャーを起動

Chromeにはブックマークを手軽に管理できるブックマークマネージャーというものがあります。

Chromeメニューから[ブックマーク] → [ブックマークマネージャ]で起動できます。

下記ショートカットでもブックマークマネージャーを起動することができます。

OS ショートカット
Windows Ctrl + Shift + O
Mac command + option + B

起動すると下記のような画面が表示されます。

ブックマークの作成

青い背景でブックマークと書かれた右側に点が縦に3つ並んでいます。
ここクリックするとフォルダをやブックマークを追加できます。

下記のようにブックマークを作成してみましょう。
なお、管理上「ハングアウト」というフォルダの中に作成しましょう。

名前 URL
録画準備
javascript:var video = null; var recorder = null; var recordedChunks = []; var interval = 0; var timerCount = 0; var started = false; var setupBord = function() { var html = '<style>.record-controller{margin: auto 5px;color:white;}</style><span class="record-controller">%E9%8C%B2%E7%94%BB%E6%99%82%E9%96%93%EF%BC%9A</span><span id="record-time" class="record-controller">-</span><span id="record-status" class="record-controller">stop</span>'; var div = document.createElement("div"); div.innerHTML = html; div.style = "float: left;top: 0px;position: absolute;"; div.style.zIndex = 10000; document.body.appendChild(div); }; var startTimer = function () { interval = setInterval(function () { var bordTimer = document.getElementById('record-time'); timerCount++; bordTimer.innerHTML = timerCount; }, 1000); }; var stopTimer = function () { clearInterval(interval); }; var setUpRecorder = function () { if (video) { return true; } var videos = document.getElementsByTagName("video"); video = getTargetVideo(videos); if (!video) { alert("video%E3%82%92%E7%89%B9%E5%AE%9A%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%9B%E3%82%93%E3%81%A7%E3%81%97%E3%81%9F%E3%80%82"); return false; } var options = { audioBitsPerSecond : 64000, videoBitsPerSecond : 512000, mimeType: 'video/webm;codecs=vp9' }; var stream = video.captureStream(); recorder = new MediaRecorder(stream, options); recorder.ondataavailable = handleDataAvailable; return true; }; var getTargetVideo = function (videos) { for (var i = 0; i < videos.length; i++) { if (!videos[i].autoplay) { continue; } return videos[i]; } }; var handleDataAvailable = function (event) { if (event.data.size > 0) { recordedChunks.push(event.data); } return; }; var download = function() { var blob = new Blob(recordedChunks, { type: 'video/webm' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); document.body.appendChild(a); a.style = 'display: none'; a.href = url; a.download = 'test.webm'; a.click(); window.URL.revokeObjectURL(url); }; var startRecord = function () { if (!setUpRecorder()) { return false; } if (!timerCount) { var bordTimer = document.getElementById('record-time'); bordTimer.innerHTML = timerCount; } if (!started) { recordedChunks = []; } if (started) { recorder.resume(); } else { started = true; recorder.start(); } startTimer(); changeRecordStatus("rec"); }; var pauseRecord = function () { recorder.pause(); stopTimer(); changeRecordStatus("pause"); }; var stopRecord = function () { started = false; recorder.stop(); stopTimer(); timerCount = 0; changeRecordStatus("stop"); }; var changeRecordStatus = function (status) { var bordTimer = document.getElementById('record-status'); bordTimer.innerHTML = status; }; setupBord();
録画開始
javascript:startRecord();
一時停止
javascript:pauseRecord();
録画終了
javascript:stopRecord();
録画を保存
javascript:download();

下記は登録した状態です。

録画準備に登録したURLは下記スクリプトから余計な空白などを除いたものです。

var video = null;
var recorder = null;
var recordedChunks = [];
var interval = 0;
var timerCount = 0;
var started = false;

var setupBord = function() {
    var html = '<style>.record-controller{margin: auto 5px;color:white;}</style><span class="record-controller">録画時間:</span><span id="record-time" class="record-controller">-</span><span id="record-status" class="record-controller">stop</span>';
    var div = document.createElement("div");
    div.innerHTML = html;
    div.style = "float: left;top: 0px;position: absolute;";
    div.style.zIndex = 10000;
    document.body.appendChild(div);
};

var startTimer = function () {
    interval = setInterval(function () {
        var bordTimer = document.getElementById('record-time');
        timerCount++;
        bordTimer.innerHTML = timerCount;
    }, 1000);
};

var stopTimer = function () {
    clearInterval(interval);
};

var setUpRecorder = function () {
    if (video) {
        return true;
    }
    
    var videos = document.getElementsByTagName("video");
    video = getTargetVideo(videos);
    if (!video) {
        alert("videoを特定できませんでした。");
        return false;
    }
    
    var options = {
        audioBitsPerSecond : 64000,
        videoBitsPerSecond : 512000,
        mimeType: 'video/webm;codecs=vp9'
    };
    
    var stream = video.captureStream();
    recorder = new MediaRecorder(stream, options);
    recorder.ondataavailable = handleDataAvailable;
    
    return true;
};

var getTargetVideo = function (videos) {
    for (var i = 0; i < videos.length; i++) {
        if (!videos[i].autoplay) {
            continue;
        }
        return videos[i];
    }
};

var handleDataAvailable = function (event) {
    if (event.data.size > 0) {
        recordedChunks.push(event.data);
    } 
    return;
};

var download = function() {
    if (!started) {
        alert("録画中・一時停止中は保存できません。");
        return false;
    }

    var blob = new Blob(recordedChunks, {
        type: 'video/webm'
    });
    var url = URL.createObjectURL(blob);
    var a = document.createElement('a');
    document.body.appendChild(a);
    a.style = 'display: none';
    a.href = url;
    a.download = 'test.webm';
    a.click();
    window.URL.revokeObjectURL(url);
    
    return true;
};

var startRecord = function () {
    if (!setUpRecorder()) {
        return false;
    }

    if (!timerCount) {
        var bordTimer = document.getElementById('record-time');
        bordTimer.innerHTML = timerCount;
    }

    if (!started) {
        recordedChunks = [];
    }

    if (started) {
        recorder.resume();
    
    } else {
        started = true;
        recorder.start();
    }
    startTimer();
    changeRecordStatus("rec");
};

var pauseRecord = function () {
    recorder.pause();
    stopTimer();
    changeRecordStatus("pause");
};

var stopRecord = function () {
    started = false;
    recorder.stop();
    stopTimer();
    timerCount = 0;
    changeRecordStatus("stop");
};

var changeRecordStatus = function (status) {
    var bordTimer = document.getElementById('record-status');
    bordTimer.innerHTML = status;
};

setupBord();

実行

それでは実際にハングアウトで実験してみましょう。

ちなみに、相手のいない待機中であれば録画ができましたが、相手が入ってきた状態だと、複数のvideoタグがあるため、うまく動作しないようです。

録画準備

録画準備を実行すると左上に「録画時間: – stop」と表示されます。

録画開始

録画開始で、左上に録画時間とともに「rec」と表示されます。

録画終了

録画終了で再び「stop」と表示されます。

ダウンロード

「録画を保存」で「test.webm」という名前でダウンロードができました。
ちゃんと撮れてる!!

あとは、複数videoタグがあるときの映像と音声を結合できるような仕組みができれば完璧!!

でも、いったんここで検証は終了。

だって有料ツールもってるんだもん。

検証後の考察

この記事の方法を使ってYoutubeコンテンツを録画できるかを試してみたところ、録画の開始まではできるものの、すぐにエラーとなってしまいました。

さすがはGoogleが提供するサービスですね。

逆にVideoタグなどで動画を提供するようなサービスを作る際には、こういった外部からの操作も可能であり、コンテンツを守るうえでは対策も必要であることが分かりますね。

ちなみに、Youtubeコンテンツのダウンロード・録画・複製は利用規約に抵触するので、検証はあまりお勧めしません。

Youtube利用規約

本コンテンツは、「現状有姿」でお客様に提供されています。お客様は、本コンテンツに、本サービスの機能により意図されており本サービス条件により認められている限度で、参考目的での個人的な利用のためにのみアクセスすることができます。お客様は、「ダウンロード」または同様のリンクが本コンテンツについて本サービス上でYouTubeにより表示されている場合を除き、いかなる本コンテンツもダウンロードしてはなりません。お客様は、YouTubeまたは関連する本コンテンツのライセンサーからの事前の書面による同意なく、コピー、複製、送信可能化、出版、翻案、配布、放送、表示、販売、ライセンス付与又はその他一切の他の目的のために利用されてはなりません。YouTube及びそのライセンサーは、本コンテンツ内で並びに本コンテンツに対して明示的に付与されていない、一切の権利を留保します。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする