前の記事で、AIカメラとSeleniumを組み合わせて、ブラウザの音楽視聴サイト(YouTube Music)で音楽を自動で流したり、止めたりするプログラムの概要と使用方法について記しました。
https://nine-num-98.blogspot.com/2021/04/ai-music-01.html
本記事では、公開したプログラムの解説について記します。
プログラム概要
GitHubに公開したプログラム
https://github.com/kotetsu99/ai_music
各プログラムの概要
(1) 01-face_detection.py: 顔検出プログラム
・画像から人物の顔を検出して、顔画像ファイルをディレクトリに保存。
(2) 02-cnn_face_train.py: 顔学習プログラム
・(1)で生成した顔画像をAIに学習させ、予測モデルを生成。
・予測モデルは、CIFAR-10
画像データセット向けのAIモデル(9層畳み込みネットワーク)の構成。本人と本人以外の2値分類モデルとする。
(3) 03-cnn_face_recognition.py: 顔認識プログラム
・(2)で生成した予測モデルを使って、テスト画像に対して顔認識を実行。
(4) 04-ai_camera.py: AIカメラプログラム
・(2)で生成した予測モデルを使って、カメラ映像上の人物をリアルタイムで顔認識。
・本人が顔認識された場合、YouTube
Musicで音楽を再生。
・本人がカメラに映らなかった場合、音楽を一時停止。
・カメラ認識開始から制限時間後に、プログラムを自動終了。
(4) 04-ai_camera.py:
について、主に解説します。上記以外のプログラムについては、↓のページに解説しております。若干の違いはありますがほぼ同じ内容です。
https://nine-num-98.blogspot.com/2020/02/ai-camera-02.html
今から取り上げる04-ai_camera.pyについても、picameraやOpenCV、Kerasを使った画像認識AIカメラに関する処理は上記のページに解説を記しております。
以下では、Seleniumによるブラウザ自動操作に関する処理について、解説します。ソースコードの上から順に見ていきます。
設定関連
まずはこちら。
# URL定数定義 PLAYLIST_URL = 'https://music.youtube.com/watch?v=0cGBTbjvwuo&list=RDAMVM0cGBTbjvwuo'
WEB_DRIVER = '/usr/bin/chromedriver'
YouTube Musicで再生するプレイリストのURLをここで定義しています。ここで定義したURLを後ほど、SeleniumによりChromiumブラウザで開きます。また、SeleniumがChromiumブラウザを操作するためには、別途ソフトウェア(webdriver)が必要です。
Chromium/Chrome用のwebdriverとして、chromedriverと呼ばれるものがあり、これを事前にインストールしておく必要があります。WEB_DRIVER にはインストールしたchromedriverのパスを記載しています。このchromedriverパスを参照して、seleniumがChromiumブラウザを起動します。
main関数
main関数の以下の箇所で、Chromiumブラウザを起動しています。
# ブラウザを起動 brws = setup_browser()
この setup_browser() という関数でブラウザの起動が行われます。この関数はmain関数の後で定義されており、後ほど解説します。 起動したブラウザは、brwsという変数(インスタンス)を用いて、任意のwebページに遷移したり、画面上のHTML要素を操作したりすることが可能となります。
カメラが起動し、whileループに入った後、ブラウザで開いているページ(YouTube Music)のプレイヤー画面の状態を確認する処理が入ります。
# 制限時間まで顔認識実行 while process_time < time_limit : # 本人認識フラグ初期化 person_flg = False # プレイヤーの状態を確認 state = check_player_state(brws)
check_player_state という関数もmain関数の後で定義されており、これも後述しますが、stateという変数にプレイヤーの再生状態:Play(再生)/Pause(一時停止)/None(プレイヤー非表示)を格納します。 このstateの値を参照してプレイヤーの再生状態を把握し、再生/一時停止処理の切り替えを適切に行います。
以下の箇所で本プログラムのメイン機能の一つである音楽プレイヤー(YouTube Music)の再生/一時停止の自動処理が記述されています。
# 本人が顔検出された場合 if (person_flg == True): # プレイヤー画面が開いていない場合、プレイヤー画面に遷移 if state == 'None': brws.get(PLAYLIST_URL) player = brws.find_element_by_tag_name('body') print('再生') # プレイヤー画面が開いている場合、再生状態とする elif state == 'Pause': # プレイヤー再生 player.send_keys(Keys.SPACE) print('再生') # 本人が顔検出されない場合 elif (person_flg == False): # プレイヤーが再生状態の場合 if state == 'Play': # プレイヤー一時停止 player.send_keys(Keys.SPACE) print('一時停止')
ラズパイのAIカメラが本人を認識(person_flg==True)した場合、プレイヤーを開くまたは再生状態にする処理を行います。プレイヤー画面が開いていない場合(state==None)プレイリストを開きます。
brws.get(PLAYLIST_URL)
というメソッドで、YouTube Musicのプレイリストが開きます。次に
player = brws.find_element_by_tag_name('body')
という処理がありますが、これはYouTube Music画面HTMLのbody要素を取得しています。このbody要素に対し、YouTube Musicの基本機能であるショートカットコマンドを送ることで、再生/一時停止の切り替えが可能です。
YouTube Musicのショートカットキーは以下の通りになっています。
----------------------------------
再生 / 一時停止: スペース
前の曲 / 次の曲: K / J
巻き戻り / 早送り: H / L
ミュート: M
リピート: R
----------------------------------
再生/一時停止の切り替えは「スペース」キーで行えます。プレイヤーが一時停止状態である場合、
player.send_keys(Keys.SPACE)
で再生を再開させることができます。一方で、本人がカメラ上で検出されなかった(person_flg == False)場合、プレイヤーが再生状態(state=='Play')であれば、以下のショートカットコマンドで一時停止状態にします。
player.send_keys(Keys.SPACE)
以上が、main関数内のプレイヤー自動操作に関する主な処理の説明になります。
ブラウザ起動関連
def setup_browser():
# ブラウザ起動オプション設定 options = webdriver.ChromeOptions() options.add_argument('--kiosk') options.add_argument('--incognito') options.add_argument('--disable-infobars') options.add_argument('--disable-extensions') # ブラウザ起動 brws = webdriver.Chrome(WEB_DRIVER, chrome_options=options) brws.set_page_load_timeout(90) return brws
Chromiumブラウザ起動関連の関数です。ブラウザの起動オプションの設定と起動処理を行っています。Chromiumブラウザは、多くのオプションが付加されており、シークレットモードで起動したり、全画面表示させたりと様々なことができます。webdriverライブラリのoptions.add_argument という命令で、ここでは以下のオプションを設定しています。
・options.add_argument('--kiosk')
キオスクモード(フルスクリーン)でChromiumを表示させます。
・options.add_argument('--incognito')
シークレットモードで起動します。余計な拡張機能をOFFにしてChromiumを起動するために設定します。
・options.add_argument('--disable-infobars')
ブラウザが自動操作されていることを通知する、バーを非表示にします。
・options.add_argument('--disable-extensions')
拡張機能を無効にします。シークレッドモードでも有効になるものがあるので、それらを完全に無効化します。
ブラウザを起動する命令は以下です。
brws = webdriver.Chrome(WEB_DRIVER, chrome_options=options)
chromedriverのファイルパスと先ほどのオプションを指定したうえで、Chromiumを起動します。Webページをロードする際のタイムアウト(待ち)時間を設定します。秒数で指定し、以下の場合では90秒です。
brws.set_page_load_timeout(90)
最後に起動したブラウザを操作するために、以下の命令で使用する変数(インスタンス)を返して終了します。
return brws
プレイヤー状態チェック
def check_player_state(brws):
if len(brws.find_elements_by_id('play-pause-button')) > 0 : player_element = brws.find_element_by_id('play-pause-button') title = player_element.get_attribute('title') # プレイヤーの再生状態に応じてstateを変更 if title == '一時停止': state = 'Play' elif title == '再生': state = 'Pause' else: # stateは'None'とする state = 'None' return state
次ですが、これはブラウザ(プレイヤー)で、表示しているYouTube Musicの再生状態を確認するための関数です。再生状態か、一時停止状態かを確認するためにはYouTube Musicの再生ボタンの状態をSeleniumで取得します。再生/一時停止ボタンは、'play-pause-button'というidが振られているhtml要素であり、まずこの要素をプログラム上で扱うための命令が以下です。
player_element = brws.find_element_by_id('play-pause-button')
ここで取得したhtml要素の属性情報のなかに、titleというものがあり、このtitle属性の内容は
・再生状態のとき、「一時停止」
・一時停止状態のとき「再生」
となります。これを利用して、プレイヤーの再生状態を把握し、state変数に現在の状態を格納します。
・title=一時停止のとき ⇒ state=Play
・title=再生のとき ⇒ state=Pause
一方で、プレイヤーのページ自体が開かれていない場合もあるため、このときのプレイヤー状態をstate変数に格納しておく必要があります。まず、YouTube Musicプレイヤーのページが開かれているか、いないかを判断するための処理が必要であり、それが
if len(brws.find_elements_by_id('play-pause-button')) > 0 :
です。先ほどの再生/一時停止ボタンが表示されているかいないかを判断するための処理です。このhtml要素の数が0より多ければボタン表示。それ以外であればボタン非表示と判断されます。ボタンが非表示と判断された場合、stateはNoneに設定されます。上記によって判断された、Play,Pause,Noneの状態をstate変数に格納して
return state
で返して関数の実行が終了します。
以上が、本プログラムの解説になります。