見出し画像

「声でマウスクリック」完成

前回の

これで、音声認識により、イベント駆動をするコードをGCAに書いてもらいました。あとはイベントと、「マウスクリック」を結び付ければいいですね。
pythonで「マウスクリック」のエミュレートをするには、pyautoguiというライブラリを使うそうです。その基本的な使い方をGCAに聞いてみました。


Gemini Code Assistに教わったpyautogui


※pyautogui 無事動作しました。

プロンプト

>pyautogui の動作確認をするサンプルコードを書いて

Gemini Code Assist(GCA)によるコードと解説

import pyautogui
import time

def test_pyautogui():
    """
    pyautoguiの基本的な動作を確認するサンプルコード
    """

    try:
        print("pyautoguiの動作テストを開始します。")

        # 1. マウスカーソルの位置を取得
        current_x, current_y = pyautogui.position()
        print(f"現在のマウスカーソルの位置: x={current_x}, y={current_y}")

        # 2. マウスを移動
        print("5秒後にマウスを(100, 100)に移動します...")
        time.sleep(5)  # 5秒待機
        pyautogui.moveTo(100, 100, duration=1)  # 1秒かけて移動
        print("マウスを(100, 100)に移動しました。")

        # 3. マウスをクリック
        print("5秒後にマウスをクリックします...")
        time.sleep(5)
        pyautogui.click()
        print("マウスをクリックしました。")

        # 4. マウスをドラッグ
        print("5秒後にマウスをドラッグします...")
        time.sleep(5)
        pyautogui.mouseDown(button='left') #左クリックを押下
        pyautogui.moveTo(300, 300, duration=1) #ドラックの終点に移動
        pyautogui.mouseUp(button='left') #左クリックを離す
        print("マウスをドラッグしました。")


        # 5. テキストを入力
        print("5秒後にテキストを入力します...")
        time.sleep(5)
        pyautogui.write("Hello, pyautogui!", interval=0.1)  # 0.1秒間隔で入力
        print("テキストを入力しました。")

        # 6. キーボードのキーを入力
        print("5秒後にEnterキーを押します...")
        time.sleep(5)
        pyautogui.press('enter')
        print("Enterキーを押しました。")

        # 7. キーの組み合わせを入力
        print("5秒後にCtrl+s (保存) を入力します...")
        time.sleep(5)
        pyautogui.hotkey('ctrl', 's')
        print("Ctrl+s (保存) を入力しました。")


        # 8.スクリーンショットをとる
        print("5秒後にスクリーンショットを取得します...")
        time.sleep(5)
        screenshot = pyautogui.screenshot()
        screenshot.save("screenshot.png")
        print("スクリーンショットを取得し、screenshot.pngに保存しました。")

        print("pyautoguiの動作テストが完了しました。")

    except Exception as e:
        print(f"エラーが発生しました: {e}")
        
if __name__ == "__main__":
    test_pyautogui()

このコードの解説:

  1. import pyautoguiとimport time: pyautoguiライブラリと時間操作のためのtimeライブラリをインポートしています。

  2. test_pyautogui()関数: pyautoguiの動作をテストするための関数です。

  3. pyautogui.position(): 現在のマウスカーソルの座標を取得します。

  4. pyautogui.moveTo(x, y, duration=n): マウスを(x, y)座標に移動します。durationで移動にかける時間を指定できます(秒単位)。

  5. pyautogui.click(): マウスをクリックします。デフォルトでは左クリックです。

  6. pyautogui.write("text", interval=n): キーボードからテキストを入力します。intervalで文字を入力する間隔を指定できます(秒単位)。

  7. pyautogui.mouseDown(button='left'): マウスのボタンを押下します。

  8. pyautogui.mouseUp(button='left'): マウスのボタンを離します。

  9. pyautogui.press('key'): キーボードの特定のキー(例:enter、esc、spaceなど)を入力します。

  10. pyautogui.hotkey('key1', 'key2'): キーの組み合わせ(例:Ctrl+s, Ctrl+c)を入力します。

  11. pyautogui.screenshot(): 現在の画面のスクリーンショットを取得します。

  12. screenshot.save("filename.png"): スクリーンショットをファイルに保存します。

  13. time.sleep(n): n秒間プログラムを一時停止します。これは、動作を確認しやすくするために入れています。

  14. try...exceptブロック: エラーが発生した場合に、エラーメッセージを表示してプログラムが停止しないようにしています。

  15. if __name__ == "__main__":: pythonのスクリプトを直接実行した場合のみ、test_pyautogui()関数を実行します。

このコードの実行方法:

  1. pyautoguiライブラリがインストールされていることを確認してください。インストールされていない場合は、以下のコマンドでインストールしてください。

    1. content_copyterminal

  2. 上記コードをpyautogui_test.pyなどのファイル名で保存します。

  3. ターミナルまたはコマンドプロンプトで以下のコマンドを実行します。

    1. content_copyterminal

注意事項:

  • pyautoguiはマウスやキーボードを自動で操作するため、意図しない動作をすることがあります。実行する前に、動作を確認しながら慎重に使用してください。

  • 動作テスト時は、他のウィンドウがアクティブになっていないことを確認してください。予期せぬ動作の原因となります。

  • マウスカーソルが動くので、実行中はマウス、キーボードから手を離して確認してください。

  • スクリーンショット機能は、pillow(PIL)ライブラリが必要になります。インストールされていない場合は、次のコマンドでインストールしてください。 pip install pillow

  • もし、エラーが発生した場合、エラーメッセージを確認し、必要なライブラリがインストールされているかを確認してください。

このサンプルコードが、pyautoguiの基本的な動作を理解するのに役立つことを願っています!

声でマウスクリック完成

pyautoguiの使い方についていろいろ説明してもらったけど、今回使うのは、
pyautogui.click() 
だけ。
マウスクリックしたのと同じ効果が発生する。前回の音声トリガのイベント部分にこの一行を入れればOKですね。


import threading
import time

import pyautogui
import speech_recognition as sr


class VoiceTrigger:
    def __init__(self, trigger_phrase, callback_function, language="ja-JP"):
        """
        音声入力をトリガーにしてイベントを起動するクラス

        Args:
            trigger_phrase (str): イベントを起動するトリガーとなるフレーズ
            callback_function (function): トリガーが検出されたときに実行する関数
            language (str): 使用する言語(デフォルトは日本語)
        """
        self.recognizer = sr.Recognizer()
        self.microphone = sr.Microphone()
        self.trigger_phrase = trigger_phrase
        self.callback_function = callback_function
        self.language = language
        self.running = False
        self.listening_thread = None

    def listen_for_trigger(self):
        """
        トリガーフレーズの検出を開始する
        """
        with self.microphone as source:
            self.recognizer.adjust_for_ambient_noise(
                source
            )  # 周囲の雑音に合わせる
            print(f"トリガーフレーズ '{self.trigger_phrase}' の検出を開始...")

            while self.running:
                try:
                    print("音声入力待ち...")
                    audio = self.recognizer.listen(
                        source, timeout=5
                    )  # 5秒間音声入力を待機

                    print("音声認識中...")
                    text = self.recognizer.recognize_google(
                        audio, language=self.language
                    )
                    print(f"認識された音声: {text}")

                    if self.trigger_phrase in text:
                        print(
                            f"トリガー '{self.trigger_phrase}' が検出されました!"
                        )
                        self.callback_function()

                except sr.UnknownValueError:
                    print("音声を認識できませんでした")
                except sr.RequestError as e:
                    print(f"音声認識サービスからの応答がありませんでした: {e}")
                except sr.WaitTimeoutError:
                    print("音声入力がありませんでした。")
                except Exception as e:
                    print(f"予期しないエラーが発生しました: {e}")

                time.sleep(0.5)  # 少しだけ待機させることでcpu負荷を軽減

    def start_listening(self):
        """
        音声認識をバックグラウンドで開始する
        """
        if self.running:
            print("すでに音声認識が開始されています。")
            return

        self.running = True
        self.listening_thread = threading.Thread(
            target=self.listen_for_trigger
        )
        self.listening_thread.daemon = True
        # メインスレッドが終了するとバックグラウンドスレッドも終了するようにする。
        self.listening_thread.start()

    def stop_listening(self):
        """
        音声認識を停止する
        """
        if not self.running:
            print("音声認識は開始されていません。")
            return

        self.running = False
        if self.listening_thread and self.listening_thread.is_alive():
            self.listening_thread.join()  # スレッドが終了するのを待つ
        print("音声認識を停止しました。")


# コールバック関数の例
def my_event():
    print("イベントが起動しました!")
    # ここに実行したい処理を記述
    pyautogui.click()
    # 例:ファイルを保存したり、プログラムを実行したり、メッセージを表示したり...


# メイン処理
if __name__ == "__main__":
    # トリガーフレーズとコールバック関数を設定
    trigger_phrase = "スタート"  # "スタート"という言葉をトリガーにする
    voice_trigger = VoiceTrigger(trigger_phrase, my_event)

    # 音声認識を開始
    voice_trigger.start_listening()

    try:
        while True:
            time.sleep(1)  # プログラムを終了させないように、1秒ごとにチェック
            # ここで他の処理を行うこともできる
    except KeyboardInterrupt:
        print("\nプログラムを終了します...")
        voice_trigger.stop_listening()

あとは、PyInstaller --onefile でEXEファイルにしておきました。 指定で1ファイル化します。一方、--noconsoleは指定しません。
 終了時はコンソールでCTRL+C。

これが、オーバーヘッドスキャナで蔵書の自炊をするときに大変便利で、作業がはかどります。早速4冊処理しました。

いいなと思ったら応援しよう!