9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Youtube動画を音声でコントロールするためのChrome拡張が生まれた。

Last updated at Posted at 2019-05-20

生まれしもの

  • Youtube再生中に
    • chrome拡張のアイコンをクリックすれば音声認識を開始し、
    • 「待って」と言えば一時停止をし、
    • 「いいよ」と言えば再生をし、
    • 「◯秒戻って」と言えば◯秒巻き戻して再生し、
    • 「◯秒進んで」と言えば◯秒早送りして再生し
    • 「終わり」と言えば音声認識を終了する

そんなchrome拡張がこの世に生まれました。

経緯

  • 「ほぇえ。Youtubeって色んな技術のサンプル実装動画あるんやなぁ」
  • 「動画見ながら写経して新しい技術触ってみるかあ」
  • 「ブラウザとエディタを2分割して両方画面に表示して、Youtube再生して写経開始っと・・・」
  • 「ちょww 解説早いww しかもww タイピングも早いw 待ってw 今どこwww」
  • 「巻き戻さなきゃ・・・。あぁ行き過ぎた・・・。うわああああシークバー動かすのめんどくせえええ」
  • 「うーむ、なんとかして写経の効率上がらないかなぁ」
  • 「SiriやらAlexaみたいに音声でコントロールできたら写経やりやすくなるのでは🤔」

という経緯で、「トラックパッド・マウス操作不要、音声でYoutubeをコントロールできる機能」の開発に着手しました。

最初はYoutube API使って自分のWebサイトに動画埋め込んで、音声認識開始・停止のボタンを用意して・・・みたいなことを考えたんですが、よく考えたらChromeの拡張機能でよくね?となったので、初めてですがChrome-extensionで作ることに。

成果物

作成にあたっては下記記事を大いに参考にさせていただきました。 ありがとうございます🙏
Chrome拡張の作り方 (超概要)
ブラウザで音声操作をする。(Speech Recognition API)

ファイルはこれだけです。本当にシンプル。Chrome拡張作ったの初めてですが、単純な機能でよければすごく簡単に作れますね。
JQueryはCDN使っても🙆‍♂️

manifest.json
background.js
content.js
jquery.min.js
manifest.json
{
	"manifest_version": 2,
	"name": "Youtube Voice Controller",
	"description": "Youtube動画を音声で操作します",
	"version": "1.0.0",
	"content_scripts": [{
		"matches": ["<all_urls>"],
		"js": ["content.js","jquery.min.js"]
	}],
	"background": {
		"scripts": ["background.js"]
	},
	"browser_action": {
		"default_title": "Youtubeを音声で操作します"
  },
	"permissions": [
		"tabs",
		"background",
		"http://*/*",
		"https://*/*"
	]
}

background.js
chrome.browserAction.onClicked.addListener(function(tab) {
	chrome.tabs.sendMessage(tab.id, "Action");
});
content.js
SpeechRecognition = webkitSpeechRecognition || SpeechRecognition;
recognition = new SpeechRecognition();
recognition.lang = 'ja-JP';
recognition.continuous = true;
recognition.maxAlternatives = 1;
var hasSpeechRecognizeStarted = false;
var userAction = false;

chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
	if (request == "Action") {
      userAction = true;
      if(hasSpeechRecognizeStarted) {
        rec_stop();
      } else {
        rec_start();
      }
	}
});

function hasSpeeched(speech, action) {
  return speech.indexOf(action) > -1;
}

function rec_start() {
  recognition.start();
  hasSpeechRecognizeStarted = true;
}

function rec_stop(){
  recognition.stop();
  hasSpeechRecognizeStarted = false;
}

function getSecondBy(speech, action) {
	switch (action) {
		case "戻って":
			return parseInt(speech.replace('秒戻って', ''), 10);
			break;
		case "進んで":
			return parseInt(speech.replace('秒進んで', ''), 10);
			break;
		default:
			break;
	}
}

recognition.onresult = (event) => {
  var transcript = event.results[event.resultIndex][0].transcript;

  if(hasSpeeched(transcript, "いいよ")){
    $('video')[0].play();
  }

  if(hasSpeeched(transcript, "待って")){
    $('video')[0].pause();
  }

  if(hasSpeeched(transcript, "戻って")){
    var second = getSecondBy(transcript, "戻って");
    $('video')[0].currentTime -= second;
    if($('video')[0].paused) {
      $('video')[0].play();
    }
  }

  if(hasSpeeched(transcript, "進んで")) {
    var second = getSecondBy(transcript, "進んで");
    $('video')[0].currentTime += second;
    if($('video')[0].paused) {
      $('video')[0].play();
    }
  }

  if(hasSpeeched(transcript, "終わり")){
    userAction = true;
    rec_stop();
  }
}

recognition.onend = (event) => {
  if(!userAction) {
    rec_start();
  }
}

やってることは至極簡単なんですが、ほんのちょっと手を加えたところは以下。

  • 音声認識を開始してしばらく沈黙していると音声認識受付を終了してしまう
    • マイクの受付終了時はonendでイベントを取得できるので、ユーザーが能動的に止めた(userActionがtrue)でなければ再度音声認識を開始する

どうなったか

  • 「ブラウザとエディタを2分割して両方表示して、Youtube再生して写経開始っと・・・」
  • 「ちょww 英語www 解説早いww しかもww タイピングも早いw 待ってw 今どこwww」
  • 「よし、ちょっと戻そう。『30秒戻って』」
  • 「あー、なるほどね そう書き方なのね 理解理解」
  • 「動画進めよう。『いいよ』」
  • 「あー、そこもうちょっとじっくり見たい! 『止まって』」
  • 「あー、なるほどね そう書き方なのね 理解理解」

という感じで今までキーボードから手を離してトラックパットを使ってシークバーを動かして位置調整をして・・・という煩わしい手順から解放されて写経の効率が著しく向上しました(当社比)。

拡張の拡張をするなら

自分が使えればいいや精神で最低限の機能しか実装しませんでしたが、今後もう少し使いやすくするためにはこんな機能をつけたいなあと思っています

  • 音声コマンドをユーザーが独自に設定できるようにする
  • ◯秒戻るのか◯分戻るのかを設定可能もしくはそれぞれを認識可能にする
  • 音声認識中を視覚的に表示する
    • 発生してから数秒ラグがあるので認識されてるかどうか分かりづらい

おまけ

最近よく見ている技術系チャンネルをあげておきます。
ドットインストールで色々写経したけどもう少し踏み込んだものをやりたい!というような人には結構おすすめです。

  • Red Stapler
    • CSSを使ったデザインなど主にフロント系のチュートリアル動画が多い印象。なんかいいデザインないかなあとよく動画を漁ります
  • Code Inspire
    • Vue.jsとFirebaseとStripe使ってECサイトを作る、などフレームワークを使って特定のものを開発するチュートリアル系動画が多い。目的がはっきりしてるのでとっかかりやすい。個人的な感想だが連載物の動画の場合、サムネイルと動画タイトルの文頭に「第何回目なのか」が明記されているのは良動画が多い。
  • Traversy Media
    • JSのフレームワークやWeb Developmentに必要なHTML, CSSをCrash Course(短期集中)で学べるチャンネル。一本一本が1時間超えていたり長い動画が多い印象。更新頻度が高い。
  • The Net Ninja
    • チュートリアルがほとんど。色んな技術のチュートリアルが上がっているので新しく触りたいものがあれば検索してみると結構出てくる。
  • Engineer Man
    • ここもチュートリアルがほとんど。サムネイルのフォントが好きじゃないという極めて個人的な理由であまり見ていない。扱っている技術は幅広いので漁ってみるとよいかも。
  • Online Tutorials
    • CSSのデザインチュートリアルがメインのチャンネル。出来上がったデザインをサムネイルでバン!と見せてくれるのがありがたい。毎日見ることは少ないけど、Webサイト作ってておしゃれなデザインに困った時に動画リストをさーっと見て、いい感じのサムネイルのものがあったら写経する、という感じで使ってます。
  • Le Wagon
    • コーディングブートキャンプを提供しているLe Wagonの(おそらく)公式Youtubeチャンネル。コーディング以外の動画も結構あるがワークショップ動画が結構あり、しかもUI、UXデザイン関連のものもあるのがいい。Youtubeのタイムラインに気になる動画があればとりあえず「あとで見る」に保存しておく系チャンネルとして利用。
  • The Coding Train
    • 個人的にめちゃくちゃおすすめのチャンネル。愉快なおじさんが愉快にライブコーディングする動画がよく上がっている。こんなに愉快にコーディングする人を見たことがないくらいめちゃくちゃ楽しそうにコーディングする。アルゴリズムや考え方をホワイトボードを使って説明したりしてくれるので理解しやすい。使用されているのはほとんどがJSのフレームワークを使ったものなので、今のところ個人的に実務で使えるものは正直あまりないが、愉快なおじさんが愉快にコーディングしているのを見ているだけでも楽しい。
  • Lets Build That App
    • これだけ少し毛色が違って、ほとんどがSwiftを使ったXcodeでのコーディング動画。よく見かけるiOSのデザインを分かりやすく解説してくれる。成果物が具体的なので写経した後に個人的にカスタマイズして使ったりしています。

これでもまだ半分くらいなので、別記事でおすすめのチャンネルをまとめたいと思います。

終わりに

  • Chrome拡張はやってみると簡単でとっかかりやすい
  • ないものは自分で作ってみる精神でよいハックライフを!
9
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?