ubuntu22.04 Live USB 作成

ubuntu22.04 Live USB 作成

【簡単】balenaEtcherを使ってUbuntuのLive USBを作成する方法
を参考に

USB3.0対応の64GBのUSBメモリを購入

なお MacBook Airには
Usb type C しかないので
変換アダプターを購入し使用

OSがダウンロードできたら
balenaEtcherをダウンロード

https://etcher.balena.io
へアクセスし
Download Etcher
をクリック

しかし
Mac のx64形式しかないので
M1Macだとできない

このため
【M1】 M1 Mac で UbuntuをUSBに焼く

を参考に進める

これには
Rosetta
を使う必要があるらしいが既に入っていた

Finder を開き
ユーティリティ > ターミナルを右クリックで開く

ちなみにMacBook Airの場合
トラックパッドを2本指でタップするとできる

Macの「右クリック」4つのやり方|キーボードでもできます

を参考に

これで右クリックができるので
情報を見る

Rosettaを利用して開く
にチェックを入れる

これでUSBメモリを差し込み
Finder からターミナルを開く

diskutil list


USBをどのように認識しているか調べる

結果は

/dev/disk0 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *251.0 GB   disk0
   1:             Apple_APFS_ISC Container disk2         524.3 MB   disk0s1
   2:                 Apple_APFS Container disk3         245.1 GB   disk0s2
   3:        Apple_APFS_Recovery Container disk1         5.4 GB     disk0s3

/dev/disk3 (synthesized):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      APFS Container Scheme -                      +245.1 GB   disk3
                                 Physical Store disk0s2
   1:                APFS Volume Macintosh HD            9.1 GB     disk3s1
   2:              APFS Snapshot com.apple.os.update-... 9.1 GB     disk3s1s1
   3:                APFS Volume Preboot                 4.6 GB     disk3s2
   4:                APFS Volume Recovery                797.2 MB   disk3s3
   5:                APFS Volume Data                    145.8 GB   disk3s5
   6:                APFS Volume VM                      6.4 GB     disk3s6

/dev/disk4 (disk image):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        +2.7 GB     disk4
   1:                        EFI EFI                     209.7 MB   disk4s1
   2:                  Apple_HFS VOICEVOX 0.14.7         2.3 GB     disk4s2

/dev/disk5 (disk image):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        +2.7 GB     disk5
   1:                        EFI EFI                     209.7 MB   disk5s1
   2:                  Apple_HFS VOICEVOX 0.14.7         2.3 GB     disk5s2

/dev/disk6 (disk image):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        +2.7 GB     disk6
   1:                        EFI EFI                     209.7 MB   disk6s1
   2:                  Apple_HFS VOICEVOX 0.14.7         2.3 GB     disk6s2

/dev/disk7 (disk image):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        +1.5 GB     disk7
   1:                  Apple_HFS Blender                 1.4 GB     disk7s1

/dev/disk8 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *62.5 GB    disk8
   1:             Windows_FAT_32 KIOXIA                  62.5 GB    disk8s1

上にあるものはOS関連
フォーマットを見ると1つだけ
/dev/disk8

Windows_FAT_32_KIOXIA
となっているので

diskutil eraseDisk MS-DOS UNTITLED /dev/disk8

を実行

Started erase on disk8
Unmounting disk
Creating the partition map
Waiting for partitions to activate
Formatting disk8s2 as MS-DOS (FAT) with name UNTITLED
512 bytes per physical sector
/dev/rdisk8s2: 121576384 sectors in 1899631 FAT32 clusters (32768 bytes/cluster)
bps=512 spc=64 res=32 nft=2 mid=0xf8 spt=32 hds=255 hid=411648 drv=0x80 bsec=121606144 bspf=14841 rdcl=2 infs=1 bkbs=6
Mounting disk
Finished erase on disk8

となって
中身が消去される

次にディスクのアウンマウント
これをやらないとISOを書き込む時にエラーになるらしい

diskutil unmountDisk /dev/disk8

を実行すると

Unmount of all volumes on disk8 was successful

となり成功

次に書き込み
ISOファイルのパスを取得するには
FinderでISOファイルをクリックし
青くなっている状態で
Command + option + c
を押すとファイルパスが取得できる

私の場合だと

/Users/snowpool/Downloads/ubuntu-ja-22.04-desktop-amd64.iso

これを
Ddコマンドの
If で指定し ofへUSBデバイスを指定する

約8分程度で

850993+1 records in
850993+1 records out
3427803136 bytes transferred in 480.772592 secs (7129781 bytes/sec)

となり書き込みが終わる

ラズパイドラレコ作成

ラズパイドラレコ作成

ssh
でアクセスし

sudo apt-get update
sudo apt-get upgrade

のあと

sudo raspi-config


最初のメニューの5番目の項目
Interfacing Optionsを開くと1番上にカメラの項目があるのでこれを有効化

ここまでできたら

v4l2-ctl --list-devices

使用するカメラのデバイスファイルを調べる
通常は

/dev/video0

となる

デバイスファイルを特定しておくと
下記のコマンドでサポートしている動画のフォーマットを表示することが可能

v4l2-ctl -d /dev/video0 --list-formats

ラズパイで動画を撮影する方法として
FFmpegを使用してリアルタイムでハードウェアエンコードする方法がよく紹介されていますが
特にRaspberry Pi Zeroだと
フレームレートがあまり出ないのでドラレコには不向き

しかしハードウェアエンコードなんてしなくても
H.264をサポートしているカメラモジュールを使用すれば
専用の動画撮影コマンドraspividを実行することで
簡単にH.264動画を撮影することが可能

安価なUSB接続のWebカメラだと
H.264をサポートしていなかったりしますが
ズパイ向けのカメラモジュールは
どれもH.264をサポートしているので
基本的にraspividで録画する

raspividで動画を撮影するには
もっともシンプルに書くなら
-oで出力ファイル名のみを指定してこのように記述
なお指定した名前のファイルが既に存在する場合は
実行に失敗するので注意

raspivid -o test.h264

このように何も指定せずに実行すると5秒の動画ファイルが生成される

拡張子がH.264と扱いにくい形式ですが
一応このままでもVLCなどの動画プレーヤーで再生することが可能 

撮影してみてカメラの向きが上下反転していた場合は-vf
左右反転していた場合は-hfを付け加えることで
正常な向きに補正されるはず

また-rotで角度を指定して回転させることもできる
shell]
raspivid -o test.h264 -rot 180[/shell]

正しい方向で撮影できるようになったら-wと-hで解像度、
-tで撮影時間、-fpsでフレームレート、-bでビットレートを指定

raspivid -o test.h264 -rot 180 -w 1280 -h 720 -t 10000 -fps 30 -b 2000000

撮影時間はミリ秒で指定するため、-t 10000だと10秒の動画を生成

ただし-t 0で時間を指定しなければずっと録画し続けることが可能

Ctrl+Cで録画を停止

解像度やビットレートを上げれば高画質な動画を撮影できますが
それに比例してファイルサイズも大きくなるので注意

raspividの実行中にWi-Fiから切断されると
コマンドラインが閉じられるために録画も停止してしまう
車内にWi-Fi環境が整っている場合はともかく、
そうでないならもう一工夫が必要

Raspberry Pi Zeroがネットワークから切断されても
raspividを停止しないようにするために、
まずコマンドを実行するシェルスクリプトを作成

sudo nano test.sh

中身は

#!/bin/sh

raspivid -o `date '+%Y%m%d-%H%M'`.h264 \
-rot 180 -w 1280 -h 720 -t 10000 -fps 30 -b 2000000

あとは

sh test.sh

で録画できればok

次は
作成したスクリプトをサービスとしてシステム管理デーモンのsystemdに登録

まずは自動実行させたいスクリプトを/optに作成

sudo nano /opt/test.sh

今回は録画時間を指定しない

#!/bin/sh

raspivid -o `date '+%Y%m%d-%H%M'`.h264 \
-rot 180 -w 1280 -h 720 -t 0 -fps 30 -b 2000000

次は

sudo chmod 0755 /opt/test.sh

で実行権限付与

このスクリプトをサービスとしてsystemdに登録するため、ユニットファイルを作成

sudo nano /etc/systemd/system/test.service

中身は

[Unit]
Description = test

[Service]
ExecStart = /opt/test.sh
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target

解説
Descriptionはユニットファイルの説明です。これは自由に記述

ExecStartに登録したいスクリプトを記述

Restartはalwaysを設定しておくことで、
プロセスが不意に終了しても再起動させることが可能です。
再起動する条件として異常終了した場合のみ、
あるいは逆に正常終了した場合のみなどを設定することも可能ですが、
通常はalwaysで良い

例外として後述するsystemctlコマンドで停止した場合のみ再起動されない

Typeはプロセスの起動タイプを設定するオプションです。
simpleがデフォルトで、メインプロセスとして登録

WantedByは弱く依存するユニットを記述します。
噛み砕いて説明すると、
multi-user.targetの起動時にtest.serviceの起動も試みてほしい、
ということです。
多くのサービスがmulti-user.targetに紐付いていて、
OS起動時にまとめて実行されます。

ユニットを定義できたら、サービスを有効化するために下記のコマンドを実行

sudo systemctl enable test.service

正常に有効化されていれば、下記のコマンドを入力するとバックグラウンドでサービスが実行されます。

サービスの状態は下記のコマンドで確認

sudo systemctl status test.service

しかし

Loaded: loaded (/etc/systemd/system/test.service; enabled; vendor preset: > Active: inactive (dead)

と表示されて固まる

Systemd を利用してサービスを追加・登録する
を参考に

systemctl list-unit-files --type=service |grep test

を実行し

glamor-test.service                        enabled         enabled
gldriver-test.service                      enabled         enabled
test.service                               enabled         enabled

で稼働しているのを確認

またサービスを手動で停止したい場合は下記のコマンドを実行

sudo systemctl stop test.service

とりあえず止めておく
理由は

ただし普通にraspividコマンドを実行すると
1つの巨大な動画ファイルが生成されてしまうので、
特にWi-Fi経由でデータを取り出そうとするとかなり時間がかかります

解決策として
FFmpegへパイプ入力して動画ファイルの分割&変換処理を自動的に実行させることで対策

https://gadget-live.net/raspberry-pi-raspivid-ffmpeg-pipe-input/
を参考に

あとは
Raspberry Pi Zeroをシャットダウンして安全に電源を切る方法

スマートフォンのテザリングでSSH接続
これだと
Bluetoothテザリング
https://gadget-live.net/raspberry-pi-bluetooth-tethering/
があるが
問題は複数のペアリングが可能かということ

Alexaを利用してハンズフリーで操作
これもありだけど
スマホでテザリングしてる状態で
Alexaが使えるのか?

とりあえずSSHでログインしてシャットダウンがベスト
あとはBluetoothボタンが候補
あとは人感センサーか音声でシャットダウンが候補

動画については
raspividからFFmpegへパイプ入力して
FFmpegのsegmentオプションで分割すれば、これらの問題がすべて簡単に解決
この方法なら録画した動画を一定時間毎に分割することも、
ファイルの名前をそれぞれの録画を開始した時間にすることも、
さらに拡張子をH.264からMP4に変換するのもすべて自動的に実行することが可能

例えば解像度1280×720、ビットレート2000kbps、
フレームレート30fpsで録画して1分単位で分割すれば
ファイルサイズは1つあたり約15MBなので、
ピンポイントで転送すればWi-Fiでもそれほど時間をかけずに取り出せます。

ようやく実際に手を動かしてraspividからFFmpegへパイプ入力するスクリプトを実装
既にドラレコとしてraspividコマンドを実行するスクリプトを組んであるなら、
それを書き換えるだけなのですごく簡単

#!/bin/sh

raspivid -o - -w 1280 -h 720 -t 0 -fps 30 -b 2000000 |
ffmpeg -r 30 -i - -vcodec copy \
-f segment -strftime 1 -segment_time 60 \
-segment_format_options movflags=+faststart -segment_format mp4 \
-reset_timestamps 1 \
/home/pi/%Y-%m-%d_%H-%M.mp4

スクリプトの完成系はこんな感じです。
これをサービスとしてsystemdに登録しておけば、ラズパイが起動すると自動的に録画を開始

raspividのオプション
オプション 説明
-o 出力ファイル名
-w,-h 解像度
-t 録画時間
-fps フレームレート
-b ビットレート

取得した動画データはFFmpegに渡すので-oでは出力ファイル名を指定しません。
録画時間に上限を設けないなら0で良いでしょう。
解像度やビットレート等はお好みで。

必要なオプションを記述したら、|でFFmpegにパイプ入力

FFmpegのオプション
オプション 説明
-r フレームレート
-i 入力ファイル
-vcodec 動画のコーデック
-strftime 出力ファイル名に日時を使用するためのオプション
-segment_time 分割時間
-segment_format_options movflags=+faststart 動画のメタデータ情報を先頭に付与する
-segment_format 分割する動画のフォーマット
-reset_timestamps セグメントのタイムスタンプのリセット

4行目以降はFFmpegについての記述になります。
見やすくするために適宜改行してありますが、もちろん不要なら改行しなくてもOK

フレームレートはraspividコマンドで指定した数字に合わせましょう。
入力ファイルについては、今回はパイプ入力するので指定しません。
動画の拡張子は変換しますがコーデックは変わらないのでcopyです。

-strftimeは出力ファイル名に日時を使用するためのオプションです。
-segment_timeで何秒毎に分割するのか時間を指定します。

-segment_format_options movflags=+faststartを記述しておくと、
動画の読み込みにかかる時間が短縮されて再生開始が早くなります。
-segment_formatはそのままです

タイムスタンプをリセットせずにセグメントファイルとして保存すると、
再生時に早送りやシークができなかったり何かと不便なことになります。
リセットしておけば普通の独立した動画として再生することが可能なので、
リセットしておきました。

最後に出力ファイル名の指定についてですが、
今回使用しているのはDATEコマンドではないので書式が異なることに注意してください。
-や_の区切り方などについては自由に書き換えて大丈夫

これをもとにファイルパスを変更し
角度を調整したのが以下のスクリプト

raspivid -o - -rot 270  -w 1280 -h 720 -t 0 -fps 30 -b 2000000 | ffmpeg -r 30 -i - -vcodec copy -f segment -strftime 1 -segment_time 60 -segment_format_options movflags=+faststart -segment_format mp4 -reset_timestamps 1 /home/snowpool/Videos/%Y-%m-%d_%H-%M.mp4

これで Videosディレクトリに1分ごとの動画が保存される

あとはこれを

sudo nano /opt/record.sh

へ記述して

問題がなければ、ラズパイの起動と同時に録画を開始するためにスクリプトをサービスとしてsystemdに登録

sudo nano /etc/systemd/system/record.service

中身は

[Unit]
Description = Drive Recorder

[Service]
ExecStart = /opt/record.sh #スクリプトのパス
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target

登録が完了したらサービスを有効化、起動

sudo systemctl enable record.service

sudo systemctl start record.service

サービスが正常に起動してスクリプトが実行されたらひとまずOK

gmail読み上げ (タイトル取得まで)

gmail読み上げ (タイトル取得まで)

ダウンロードしたファイルをコピーしてリネームする
詳細は
https://developers.google.com/gmail/api/quickstart/python?hl=ja
にあるが
とりあえず
credentials.json
にしておく

cd Downloads
cp client_secret_336287491272-faqvqnb4hjrg4ragurjh8nfhn2s3ujkg.apps.googleusercontent.com.json credentials.json

のあと作業ディレクトリ作成

mkdir -p mail_auto

ここへ認証ファイルの credentials.json をコピーする

あとはライブラリのインストール

pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

次に
quickstart.py
を作成し
コピペして動作確認

from __future__ import print_function

import os.path

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']


def main():
    """Shows basic usage of the Gmail API.
    Lists the user's Gmail labels.
    """
    creds = None
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

    try:
        # Call the Gmail API
        service = build('gmail', 'v1', credentials=creds)
        results = service.users().labels().list(userId='me').execute()
        labels = results.get('labels', [])

        if not labels:
            print('No labels found.')
            return
        print('Labels:')
        for label in labels:
            print(label['name'])

    except HttpError as error:
        # TODO(developer) - Handle errors from gmail API.
        print(f'An error occurred: {error}')


if __name__ == '__main__':
    main()

保存したら

python3 quickstart.py

で実行

この時に認証画面が出るが
セキュリティの危険があるような警告が出る
これはサーバーのオレオレ証明書の時のようなものなので
気にせず続ける

認証が終わると
メールのラベル一覧が表示される

M1MacBookAir でVOICEVOX

Windows/Macに入れたVOICEVOXをPython経由で使う方法

ラズパイ等の非力なPCからPythonやcurlで呼び出し使う方法
が載っていた

残念ながら
NVIDIA製のGPUを持っていないので
とりあえずM1Mac で動かしてみて
できるようならラズパイ4から実行してみる

まずはM1Mac で実行

https://voicevox.hiroshiba.jp/how_to_use/
でダウンロードをクリック

OSの選択をするときにMac にすると
CPUのみの選択になる

パッケージは
インストーラを選択

ダウンロード後に起動しようとしたけど
VOICEVOX”は、開発元を検証できないため開けません。
となるため

https://voicevox.hiroshiba.jp/how_to_use/
を参考に
アップルメニューから「システム環境設定」を選択して「セキュリティとプライバシー」 をクリックしこのまま開くをクリックすることで起動

もしくは
Finder で ctrを押しながら開くことでも可能

使い方の細かい説明は
https://voicevox.hiroshiba.jp/how_to_use/
を参考に

とりあえずインストールはできたので
Voicevox core を使うようにする

Raspberry PiでVOICEVOXに可愛くしゃべってもらおう
では
ラズパイで実行しているけど
M1macで実行してるのを調べたら

VOICEVOX ENGINE(API)のスループット検証

インストール先のディレクトリに移動して、以下のコマンドを実行
とあるので
まずはインストール先ディレクトリを探す

https://voicevox.hiroshiba.jp/qa/
によれば
Mac 版

/Applications/VOICEVOX もしくは /Users/(ユーザー名)/Applications/VOICEVOX

とあったけど
Ls コマンドで調べたら

ls -a /Applications/VOICEVOX.app/Contents/MacOS/

でこの中のディレクトリに
Run が入っていた

cd /Applications/VOICEVOX.app/Contents/MacOS 

で移動し

./run

を実行したけど
VOICEVOXを動かしている状態だとエラーになる

以下エラーログ

Warning: cpu_num_threads is set to 0. ( The library leaves the decision to the synthesis runtime )
INFO:     Started server process [43567]
INFO:     Waiting for application startup.
reading /Users/snowpool/Library/Application Support/voicevox-engine/tmpjvxkxzht ... 64
emitting double-array: 100% |###########################################| 

done!
INFO:     Application startup complete.
ERROR:    [Errno 48] error while attempting to bind on address ('127.0.0.1', 50021): address already in use
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.

一度VOICEVOXを終了し再度実行

Warning: cpu_num_threads is set to 0. ( The library leaves the decision to the synthesis runtime )
INFO:     Started server process [43611]
INFO:     Waiting for application startup.
reading /Users/snowpool/Library/Application Support/voicevox-engine/tmpnlpnbr_w ... 64
emitting double-array: 100% |###########################################| 

done!
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:50021 (Press CTRL+C to quit)
    

となり起動したので
http://127.0.0.1:50021
へアクセスしたけど

{"detail":"Not Found"}

となってしまう

chmod 755 run
./run --host 0.0.0.0

の後に
https://0.0.0.0:50021
でアクセスすると
ページを開けません
0.0.0.0:50021はアドレスが無効なため開けません
となる

よく調べたら
http://127.0.0.1:50021/docs
が正解だった

これでAPIドキュメントが表示される

Yolov8 を M1 Mac で使う

Yolov8 を M1 Mac で使う

YOLOv8導入まとめ
を参考に

pip install ultralytics

を実行

物体検出

yolo predict model=yolov8n.pt source='https://ultralytics.com/images/bus.jpg'

というように
Source に画像ファイルを指定すればOKみたい

物体検出ではなくセグメンテーションしたい場合は、yolov8n.ptではなくyolov8n-seg.ptを使う

yolo predict model=yolov8n-seg.pt source='https://ultralytics.com/images/bus.jpg'

これもsourceで画像ファイルを指定する

コマンドを実行すると

runs/detect/predict/

に指定したファイル名と同じファイル名で検出結果が作成される
とあるが

Results saved to runs/detect/predict

でどこに保存されているかわからないため

更新日が最近のファイルを見つける(findコマンド)
を参考に

find . -mtime -1 -ls | top

で検索し

ls ./runs/detect/predict 

でファイルができているのを確認

Finder から開くと面倒なので

MacでターミナルからFinderを開くコマンド「open」
を参考に

open .

でカレントディレクトリを Finder で開いて確認

ちなみに
yolov8n.pt
yolov8n-seg.pt

Nはモデルのサイズで
x > l > m > s > n
の順に大きなモデルになっている

xが最も大きいモデルで、nが最も小さいモデル

大きいモデルは検出にパワーが必要になるものの、検出精度が高くなる

xサイズのモデルで検出なら

yolo predict model=yolov8x.pt source='https://ultralytics.com/images/bus.jpg'

M1Mac 16GB で22秒ほどで処理できた

ポーズ検出には
yolov8x.ptの代わりにyolov8x-pose.ptを使う

yolo predict model=yolov8x-pose.pt source='https://ultralytics.com/images/bus.jpg'

これで
首から上が緑、腕が青、体がパープル、足がオレンジ色で、それぞれポーズが検出される

大体20秒くらいで処理

yolov8n.pt、yolov8n-seg.pt、yolov8n-pose.ptなどについての情報は、YOLOv8 Modelsにある

なおGPUを活用するには
Google Colaboratory
を使う

ちなみに興味があったんで
maMacbookAir 16GBでどのくらいかかるか実験

yolo predict model=yolov8x-seg.pt source='https://youtu.be/Zgi9g1ksQHc'

を実験したけど

Ultralytics YOLOv8.0.132 🚀 Python-3.10.6 torch-2.0.1 CPU
YOLOv8x-seg summary (fused): 295 layers, 71797696 parameters, 0 gradients

ERROR: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see  https://yt-dl.org/update  on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.
Traceback (most recent call last):
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 815, in wrapper
    return func(self, *args, **kwargs)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 836, in __extract_info
    ie_result = ie.extract(url)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/extractor/common.py", line 534, in extract
    ie_result = self._real_extract(url)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/extractor/youtube.py", line 1794, in _real_extract
    'uploader_id': self._search_regex(r'/(?:channel|user)/([^/?&#]+)', owner_profile_url, 'uploader id') if owner_profile_url else None,
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/extractor/common.py", line 1012, in _search_regex
    raise RegexNotFoundError('Unable to extract %s' % _name)
youtube_dl.utils.RegexNotFoundError: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see  https://yt-dl.org/update  on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/pafy/backend_youtube_dl.py", line 40, in _fetch_basic
    self._ydl_info = ydl.extract_info(self.videoid, download=False)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 808, in extract_info
    return self.__extract_info(url, ie, download, extra_info, process)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 824, in wrapper
    self.report_error(compat_str(e), e.format_traceback())
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 628, in report_error
    self.trouble(error_message, tb)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/youtube_dl/YoutubeDL.py", line 598, in trouble
    raise DownloadError(message, exc_info)
youtube_dl.utils.DownloadError: ERROR: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see  https://yt-dl.org/update  on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/snowpool/.pyenv/versions/3.10.6/bin/yolo", line 8, in <module>
    sys.exit(entrypoint())
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/cfg/__init__.py", line 407, in entrypoint
    getattr(model, mode)(**overrides)  # default args from model
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/torch/utils/_contextlib.py", line 115, in decorate_context
    return func(*args, **kwargs)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/engine/model.py", line 255, in predict
    return self.predictor.predict_cli(source=source) if is_cli else self.predictor(source=source, stream=stream)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/engine/predictor.py", line 195, in predict_cli
    for _ in gen:  # running CLI inference without accumulating any outputs (do not modify)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/torch/utils/_contextlib.py", line 35, in generator_context
    response = gen.send(None)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/engine/predictor.py", line 222, in stream_inference
    self.setup_source(source if source is not None else self.args.source)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/engine/predictor.py", line 203, in setup_source
    self.dataset = load_inference_source(source=source, imgsz=self.imgsz, vid_stride=self.args.vid_stride)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/data/build.py", line 159, in load_inference_source
    dataset = LoadStreams(source, imgsz=imgsz, vid_stride=vid_stride)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/data/dataloaders/stream_loaders.py", line 48, in __init__
    s = get_best_youtube_url(s)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/ultralytics/yolo/data/dataloaders/stream_loaders.py", line 386, in get_best_youtube_url
    return pafy.new(url).getbest(preftype='mp4').url
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/pafy/pafy.py", line 124, in new
    return Pafy(url, basic, gdata, size, callback, ydl_opts=ydl_opts)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/pafy/backend_youtube_dl.py", line 31, in __init__
    super(YtdlPafy, self).__init__(*args, **kwargs)
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/pafy/backend_shared.py", line 97, in __init__
    self._fetch_basic()
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/pafy/backend_youtube_dl.py", line 43, in _fetch_basic
    raise IOError(str(e).replace('YouTube said', 'Youtube says'))
OSError: ERROR: Unable to extract uploader id; please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see  https://yt-dl.org/update  on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.

で終了してしまった

とりあえず静止画像はここまででできそうなので
【やってみた】YOLOv8の機能試す&Webカメラでリアルタイム推論
を参考に
リアルタイムでできるようにする

ラズパイゼロで ダイレクト TCP ストリーミングでの配信と opencv で MacBookAir で再生

ラズパイゼロで
ダイレクト TCP ストリーミングでの配信と
opencv で MacBookAir で再生

とりあえずラズパイゼロWをセット

sudo apt-get update
sudo apt-get upgrade

のあと

sudo raspi-config


最初のメニューの5番目の項目、Interfacing Optionsを開くと1番上にカメラの項目があるのでこれを有効化

再起動になるので
再度SSHで接続する

ラズパイゼロだと非力なので画像処理などは難しそうだけど
とりあえず
v4l2-ctl –list-devices
使用するカメラのデバイスファイルを調べる

結果は

bcm2835-codec-decode (platform:bcm2835-codec):
	/dev/video10
	/dev/video11
	/dev/video12
	/dev/video18
	/dev/video31
	/dev/media2

bcm2835-isp (platform:bcm2835-isp):
	/dev/video13
	/dev/video14
	/dev/video15
	/dev/video16
	/dev/video20
	/dev/video21
	/dev/video22
	/dev/video23
	/dev/media0
	/dev/media1

mmal service 16.1 (platform:bcm2835_v4l2-0):
	/dev/video0

次に

v4l2-ctl -d /dev/video0 --list-formats


サポートしている動画のフォーマットを表示

結果は

ioctl: VIDIOC_ENUM_FMT
	Type: Video Capture

	[0]: 'YU12' (Planar YUV 4:two:0)
	[1]: 'YUYV' (YUYV 4:two:2)
	[2]: 'RGB3' (24-bit RGB 8-8-8)
	[3]: 'JPEG' (JFIF JPEG, compressed)
	[4]: 'H264' (H.264, compressed)
	[5]: 'MJPG' (Motion-JPEG, compressed)
	[6]: 'YVYU' (YVYU 4:two:2)
	[7]: 'VYUY' (VYUY 4:two:2)
	[8]: 'UYVY' (UYVY 4:two:2)
	[9]: 'NV12' (Y/UV 4:two:0)
	[10]: 'BGR3' (24-bit BGR 8-8-8)
	[11]: 'YV12' (Planar YVU 4:two:0)
	[12]: 'NV21' (Y/VU 4:two:0)
	[13]: 'RX24' (32-bit XBGR 8-8-8-8)

ラズパイで動画を撮影する方法として、FFmpegを使用してリアルタイムでハードウェアエンコードする方法がよく紹介されていますが、特にRaspberry Pi Zeroだとフレームレートがあまり出ないのでドラレコには不向き

しかしハードウェアエンコードなんてしなくても、H.264をサポートしているカメラモジュールを使用すれば、専用の動画撮影コマンドraspividを実行することで簡単にH.264動画を撮影することが可能

安価なUSB接続のWebカメラだとH.264をサポートしていなかったりしますが、私が確認した限りではラズパイ向けのカメラモジュールはどれもH.264をサポートしているので、基本的にraspividで録画することをおすすめ

raspividで動画を撮影するには
もっともシンプルに書くなら、-oで出力ファイル名のみを指定してこのように記述
なお指定した名前のファイルが既に存在する場合は実行に失敗するので注意

raspivid -o test.h264

このように何も指定せずに実行すると5秒の動画ファイルが生成される

とりあえず動画撮影はできたので
UDP配信をしてみる

これにはUDPストリーミング配信先のIPアドレスが必要
MacbookAir でまずは実験するので
LanScanでネットワークのIPアドレスを表示

192.168.1.137がアドレスなのが判明したので

RaspberryPiをWebカメラとして使用する
を参考に

raspivid -a 12 -t 0 -w 1920 -h 1080 -hf -ih -fps 30 -o udp://192.168.1.137:5000

を実行しても

mmal: Failed to write buffer data (2470 from 5350)- aborting
mmal: Failed to write buffer data (2739 from 8877)- aborting

となってしまう

raspivid -a 12 -t 0 -w 1920 -h 1080 -vf -ih -fps 30 -l -o tcp://0.0.0.0:5000


ダイレクト TCP ストリーミング
はできた

リモートの環境のPythonからOpenCVを使い、手元のWebカメラの映像を読みたい
を参考に

vim camera.py  

import cv2
cap = cv2.VideoCapture("tcp://192.168.1.215:5000") # 配信のURLを指定

while True:
  k = cv2.waitKey(1)
  if k == 27: # ESC key
    break

  ret, frame = cap.read()
  if not ret:
    continue

  cv2.imshow('Raw Frame', frame)

cap.release()
cv2.destroyAllWindows()

で保存

これで実行するとmac でラズパイゼロの動画が表示できる

後はここから mac側で画像認識とかできるかテストしていく

stable diffusion web UI のインストールログ

stable diffusion web UI のインストールログ

https://mac-ra.com/mac-automatic1111-stable-diffusion-webui/#toc_id_1
を参考に

brew install cmake protobuf rust python@3.10 git wget

で必要なものをインストール

しかし

Error: No developer tools installed.
Install the Command Line Tools:
 xcode-select --install

が出る

エラーを元に検索
https://techracho.bpsinc.jp/wingdoor/2021_04_09/104821
を参考に

sudo xcode-select --install

めっちゃ時間がかかる

終わったら
再度

brew install cmake protobuf rust python@3.10 git wget

これで成功

cd ~
git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui

今回はモデルとして
AOM3_orangemixs.safetensors
を使ってみた

AOM3_orangemixs.safetensors

をダウンロードして移動してみる

https://mac-ra.com/mac-automatic1111-stable-diffusion-webui/#toc_id_1
によれば
ckpt、safetensors などのモデルの置き場は、この models/Stable-diffusion フォルダになる

cp Downloads/AOM3_orangemixs.safetensors stable-diffusion-webui/models/Stable-diffusion 

でファイルをコピー

cd ~/stable-diffusion-webui
./webui.sh

でインストール開始

http://127.0.0.1:7860
とでたら safari でアクセス

後はこれで好みのモデルがあれば

stable-diffusion-webui/models/Stable-diffusion
へコピー

ネガティブプロンプトも rola のようにまとめてあるものがあるので
EasyNegative.safetensors

をダウンロード

 cp Downloads/EasyNegative.safetensors stable-diffusion-webui/embeddings 

ネガティブプロンプトに「EasyNegative」と入力する

ラズパイドラレコ作成

ラズパイドラレコ作成

ssh
でアクセスし

sudo apt-get update
sudo apt-get upgrade

のあと

sudo raspi-config


最初のメニューの5番目の項目、Interfacing Optionsを開くと1番上にカメラの項目があるのでこれを有効化

ここまでできたら

v4l2-ctl --list-devices

使用するカメラのデバイスファイルを調べる
通常は
/dev/video0
となる

デバイスファイルを特定しておくと
下記のコマンドでサポートしている動画のフォーマットを表示することが可能

v4l2-ctl -d /dev/video0 --list-formats

ラズパイで動画を撮影する方法として
FFmpegを使用してリアルタイムで
ハードウェアエンコードする方法がよく紹介されてるが
特にRaspberry Pi Zeroだと
フレームレートがあまり出ないのでドラレコには不向き

しかしハードウェアエンコードなんてしなくても
H.264をサポートしているカメラモジュールを使用すれば
専用の動画撮影コマンドraspividを実行することで
簡単にH.264動画を撮影することが可能

安価なUSB接続のWebカメラだとH.264をサポートしていなかったりするが
ラズパイ向けのカメラモジュールはH.264をサポートしているので
基本的にraspividで録画する

raspividで動画を撮影するには
もっともシンプルに書くなら
-oで出力ファイル名のみを指定してこのように記述

なお指定した名前のファイルが既に存在する場合は実行に失敗するので注意

raspivid -o test.h264

このように何も指定せずに実行すると5秒の動画ファイルが生成される

拡張子がH.264
一応このままでもVLCなどの動画プレーヤーで再生することが可能 

撮影してみてカメラの向きが上下反転していた場合は-vf
左右反転していた場合は-hfを付け加えることで正常な向きに補正されるはず

また-rotで角度を指定して回転させることもできる

raspivid -o test.h264 -rot 180

正しい方向で撮影できるようになったら
-wと-hで解像度
-tで撮影時間
-fpsでフレームレート
-bでビットレートを指定

raspivid -o test.h264 -rot 180 -w 1280 -h 720 -t 10000 -fps 30 -b 2000000

撮影時間はミリ秒で指定するため
-t 10000だと10秒の動画を生成

ただし-t 0で時間を指定しなければ
ずっと録画し続けることが可能

Ctrl+Cで録画を停止

解像度やビットレートを上げれば高画質な動画を撮影できるが
それに比例してファイルサイズも大きくなるので注意

raspividの実行中にWi-Fiから切断されると
コマンドラインが閉じられるために録画も停止してしまう
車内にWi-Fi環境が整っている場合はともかく
そうでないならもう一工夫が必要

Raspberry Pi Zeroがネットワークから切断されても
raspividを停止しないようにするために
まずコマンドを実行するシェルスクリプトを作成

sudo nano test.sh

中身は

#!/bin/sh

raspivid -o `date '+%Y%m%d-%H%M'`.h264 \
-rot 180 -w 1280 -h 720 -t 10000 -fps 30 -b 2000000

あとは

sh test.sh

で録画できればok

次は
作成したスクリプトをサービスとしてシステム管理デーモンのsystemdに登録

まずは自動実行させたいスクリプトを/optに作成

sudo nano /opt/test.sh

今回は録画時間を指定しない

#!/bin/sh

raspivid -o `date '+%Y%m%d-%H%M'`.h264 \
-rot 180 -w 1280 -h 720 -t 0 -fps 30 -b 2000000

次は

sudo chmod 0755 /opt/test.sh

で実行権限付与

このスクリプトをサービスとしてsystemdに登録するため、ユニットファイルを作成

sudo nano /etc/systemd/system/test.service

中身は

[Unit]
Description = test

[Service]
ExecStart = /opt/test.sh
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target

解説
Descriptionはユニットファイルの説明
これは自由に記述

ExecStartに登録したいスクリプトを記述

Restartはalwaysを設定しておくことで
プロセスが不意に終了しても再起動させることが可能

再起動する条件として異常終了した場合のみ
あるいは逆に正常終了した場合のみなどを設定することも可能だが
通常はalwaysで良い

例外として
systemctlコマンドで停止した場合のみ再起動されない

Typeはプロセスの起動タイプを設定するオプション
simpleがデフォルトで
メインプロセスとして登録

WantedByは弱く依存するユニットを記述
multi-user.targetの起動時にtest.serviceの起動も試みてほしい、ということ

多くのサービスがmulti-user.targetに紐付いていて、OS起動時にまとめて実行される

ユニットを定義できたら、サービスを有効化するために下記のコマンドを実行

sudo systemctl enable test.service

正常に有効化されていれば、下記のコマンドを入力するとバックグラウンドでサービスが実行されます。

サービスの状態は下記のコマンドで確認

sudo systemctl status test.service

しかし

Loaded: loaded (/etc/systemd/system/test.service; enabled; vendor preset: > Active: inactive (dead)

と表示されて固まる

Systemd を利用してサービスを追加・登録する
を参考に

systemctl list-unit-files --type=service |grep test

を実行し

glamor-test.service                        enabled         enabled
gldriver-test.service                      enabled         enabled
test.service                               enabled         enabled

で稼働しているのを確認

またサービスを手動で停止したい場合は下記のコマンドを実行

sudo systemctl stop test.service

とりあえず止めておく
理由は

ただし普通にraspividコマンドを実行すると
1つの巨大な動画ファイルが生成されてしまう

特にWi-Fi経由でデータを取り出そうとするとかなり時間がかかる

解決策として
FFmpegへパイプ入力して動画ファイルの分割&変換処理を自動的に実行させることで対策

https://gadget-live.net/raspberry-pi-raspivid-ffmpeg-pipe-input/
を参考に

あとは
Raspberry Pi Zeroをシャットダウンして安全に電源を切る方法

スマートフォンのテザリングでSSH接続
これだと

Bluetoothテザリング
があるが
問題は複数のペアリングが可能かということ

Alexaを利用してハンズフリーで操作
これもありだけど
スマホでテザリングしてる状態で
Alexaが使えるのか?

とりあえずSSHでログインしてシャットダウンがベスト
あとはBluetoothボタンが候補
あとは人感センサーか音声でシャットダウンが候補

動画については
raspividからFFmpegへパイプ入力してFFmpegのsegmentオプションで分割すれば
これらの問題がすべて簡単に解決
この方法なら録画した動画を一定時間毎に分割することも
ファイルの名前をそれぞれの録画を開始した時間にすることも
さらに拡張子をH.264からMP4に変換するのもすべて自動的に実行することが可能

例えば解像度1280×720
ビットレート2000kbps
フレームレート30fpsで録画して1分単位で分割すれば
ファイルサイズは1つあたり約15MBなので
ピンポイントで転送すればWi-Fiでもそれほど時間をかけずに取り出せる

raspividからFFmpegへパイプ入力するスクリプトを実装
既にドラレコとしてraspividコマンドを実行するスクリプトを組んであるなら
それを書き換えるだけなのですごく簡単

#!/bin/sh

raspivid -o - -w 1280 -h 720 -t 0 -fps 30 -b 2000000 |
ffmpeg -r 30 -i - -vcodec copy \
-f segment -strftime 1 -segment_time 60 \
-segment_format_options movflags=+faststart -segment_format mp4 \
-reset_timestamps 1 \
/home/pi/%Y-%m-%d_%H-%M.mp4

スクリプトの完成系はこんな感じ
これをサービスとしてsystemdに登録しておけば
ラズパイが起動すると自動的に録画を開始

raspividのオプション
オプション 説明
-o 出力ファイル名
-w,-h 解像度
-t 録画時間
-fps フレームレート
-b ビットレート

取得した動画データはFFmpegに渡すので-oでは出力ファイル名を指定しない

録画時間に上限を設けないなら0で良い
解像度やビットレート等はお好みでOK

必要なオプションを記述したら、|でFFmpegにパイプ入力

FFmpegのオプション
オプション 説明
-r フレームレート
-i 入力ファイル
-vcodec 動画のコーデック
-strftime 出力ファイル名に日時を使用するためのオプション
-segment_time 分割時間
-segment_format_options movflags=+faststart 動画のメタデータ情報を先頭に付与する
-segment_format 分割する動画のフォーマット
-reset_timestamps セグメントのタイムスタンプのリセット

4行目以降はFFmpegについての記述

フレームレートはraspividコマンドで指定した数字に合わせる

入力ファイルについては今回はパイプ入力するので指定しない
動画の拡張子は変換するがコーデックは変わらないのでcopy

-strftimeは出力ファイル名に日時を使用するためのオプション
segment_timeで何秒毎に分割するのか時間を指定

-segment_format_options movflags=+faststartを記述しておくと
動画の読み込みにかかる時間が短縮されて再生開始が早くなる
-segment_formatはそのまま

タイムスタンプをリセットせずにセグメントファイルとして保存すると
再生時に早送りやシークができなかったり何かと不便なことになる
リセットしておけば普通の独立した動画として再生することが可能なのでリセット

出力ファイル名の指定で
今回使用しているのはDATEコマンドではないので書式が異なることに注意
-や_の区切り方などについては自由に書き換えて大丈夫

これをもとにファイルパスを変更し
角度を調整したのが以下のスクリプト

raspivid -o - -rot 270  -w 1280 -h 720 -t 0 -fps 30 -b 2000000 | ffmpeg -r 30 -i - -vcodec copy -f segment -strftime 1 -segment_time 60 -segment_format_options movflags=+faststart -segment_format mp4 -reset_timestamps 1 /home/snowpool/Videos/%Y-%m-%d_%H-%M.mp4

これで Videosディレクトリに1分ごとの動画が保存される

あとはこれを

sudo nano /opt/record.sh

へ記述して

問題がなければ、ラズパイの起動と同時に録画を開始するためにスクリプトをサービスとしてsystemdに登録

sudo nano /etc/systemd/system/record.service

中身は

[Unit]
Description = Drive Recorder

[Service]
ExecStart = /opt/record.sh #スクリプトのパス
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target

登録が完了したらサービスを有効化、起動

sudo systemctl enable record.service

sudo systemctl start record.service

サービスが正常に起動してスクリプトが実行されたらひとまずOK

ラズパイOS書き込み

ラズパイOS書き込み

M1MacbookAir で
Raspberry Pi Imager
を使い
OSを microSD へ書き込み

https://www.raspberrypi.com/software/
からダウンロード

以前はNOOBSから簡単にダウンロードして
インストールだったけど
今はこの方法が公式らしい

https://gadget-live.net/raspberry-pi-zero-drive-recorder/

Raspberry Pi Zeroの対応フォーマット的にmicroSDHC規格しか使えないため、容量は基本的に最大32GB
とあったので
Raspberry Pi Zero 64gb
で調べたら

https://pentan.info/rp/microsd_capacity.html
によれば最大容量は512GBまで大丈夫らしい

Raspberry Pi Zero、1および2で使用されているSoCのバージョンには
制約があるため、SDカードのパーティションサイズの制限は256GBです
とのこと

そういえば初期設定で色々Wi-Fiとか設定できるらしいので
これを調べる

Raspberry Pi Imager アップデート! イメージ書き込みと同時にWiFi やSSH 接続が設定できるようになりました! #RaspberryPi
によればWi-Fiの設定が可能
なお Mac から行うとキーチェーンを使って
そのまま設定ができた

またタイムゾーンの設定も可能だったのでしておく

公開鍵の設定が分かりにくかったので検索

ラズパイ(Raspberry Pi 4 Model B)をSSDブートにする(備忘録)

によれば
まず公開鍵ファイルを作成し
.pub の公開鍵ファイルの中身をコピペすればOKらしい

とりあえず作成するけど
ファイル名を分けないと分かりにくいので
https://www.ni4.jp/2021/01/31-134600.html
を参考に
-f オプションをつけてファイル名を指定する

cd .ssh 
ssh-keygen -t rsa -f id_rsa_pizero

で作成

なお
-C “”
をつけると
作成時の自分の情報を削除できるらしい

作成後

cat id_rsa_pizero

でファイルの中身を表示し
これをコピペすれば完成

Mac で音声認識 pyttsx3

Mac で音声認識

Python で音声認識をする

Pythonで日本語を音声認識をして音声をテキスト化し、それを音声合成して発音する方法簡単解説【オウム返し by Mac その1:音声認識編】
を参考に

pip install speechrecognition

でインストール

import subprocess
import tempfile
 
 
# 音声入力
while True:
    r = sr.Recognizer()
    with sr.Microphone() as source:
        print("何かお話しして下さい。")
        audio = r.listen(source)
 
    try:
        # Google Web Speech APIで音声認識
        text = r.recognize_google(audio, language="ja-JP")
    except sr.UnknownValueError:
        print("Google Web Speech APIは音声を認識できませんでした。")
    except sr.RequestError as e:
        print("GoogleWeb Speech APIに音声認識を要求できませんでした;"
              " {0}".format(e))
    else:
        print(text)
    if text == "終わりだよ":
        break
print("完了。")

Mic,py

として実行したけど

Traceback (most recent call last):
  File "/Users/snowpool/mic.py", line 7, in <module>
    r = sr.Recognizer()
NameError: name 'sr' is not defined. Did you mean: 'str'?

となる

pip install Pyaudio

を実行したが

Building wheel for Pyaudio (pyproject.toml) ... error
  error: subprocess-exited-with-error
  
  × Building wheel for Pyaudio (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [18 lines of output]
      running bdist_wheel
      running build
      running build_py
      creating build
      creating build/lib.macosx-12.5-arm64-cpython-310
      creating build/lib.macosx-12.5-arm64-cpython-310/pyaudio
      copying src/pyaudio/__init__.py -> build/lib.macosx-12.5-arm64-cpython-310/pyaudio
      running build_ext
      building 'pyaudio._portaudio' extension
      creating build/temp.macosx-12.5-arm64-cpython-310
      creating build/temp.macosx-12.5-arm64-cpython-310/src
      creating build/temp.macosx-12.5-arm64-cpython-310/src/pyaudio
      clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -DMACOS=1 -I/usr/local/include -I/usr/include -I/opt/homebrew/include -I/Users/snowpool/.pyenv/versions/3.10.6/include/python3.10 -c src/pyaudio/device_api.c -o build/temp.macosx-12.5-arm64-cpython-310/src/pyaudio/device_api.o
      src/pyaudio/device_api.c:9:10: fatal error: 'portaudio.h' file not found
      #include "portaudio.h"
               ^~~~~~~~~~~~~
      1 error generated.
      error: command '/usr/bin/clang' failed with exit code 1
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for Pyaudio
Failed to build Pyaudio
ERROR: Could not build wheels for Pyaudio, which is required to install pyproject.toml-based projects

となる

PythonのSpeechRecognitionでマイク録音と文字起こしを簡単実装
を参考に

brew install portaudio

のあと

pip install PyAudio

でインストール成功

しかし

pip install speech_recognition

を実行すると

ERROR: Could not find a version that satisfies the requirement speech_recognition (from versions: none)
ERROR: No matching distribution found for speech_recognition

となる

とりあえず

Mkdir test_cpt
Cd test_gpt
Vim mic.py

として

import speech_recognition as sr

r = sr.Recognizer()
with sr.Microphone() as input:
    print("録音中:")
    audio = r.listen(input)

で保存し

Python mic.py

を実行すれば
録音中
と表示された

あとは

text = r.recognize_google(audio, language='ja-JP')

として
録音したデータをrecognize_google関数の引数に与えるだけ
第二引数のlanguageを変えれば英語とか他の言語として文字起こしできるらしい

入れる場所がいまいちわからんので
音声入力で文章作成するアプリの作り方【Python】

を参考にやってみる

Python】音声認識ライブラリのSpeechRecognitionでサクッと文字起こし
を参考に

もう少しやりやすく実際にマイクの認識と文字列かだけにしたいので

# micro.py

import speech_recognition as sr

for index, name in enumerate(sr.Microphone.list_microphone_names()):
    print("Microphone with name \"{1}\" found for `Microphone(device_index={0})`".format(index, name))

の実行結果は

Microphone with name "MacBook Airのマイク" found for `Microphone(device_index=0)`
Microphone with name "MacBook Airのスピーカー" found for `Microphone(device_index=1)`

これをもとに

# voice_test.py

import speech_recognition as sr

r = sr.Recognizer()

with sr.Microphone(device_index=0) as source:
    print('録音中: ')
    audio = r.listen(source)

try:
    text = r.recognize_google(audio, language='ja-JP')
    print(text)
except:
    print("録音されていません")

を実行

しかし
録音されていません
となる

# voice_test.py

import speech_recognition as sr

r = sr.Recognizer()

with sr.Microphone(device_index=0) as source:
    print('録音中: ')
    audio = r.listen(source)

try:
    text = r.recognize_google(audio, language='ja-JP')
    print(text)

    # 録音された音声をファイルへ保存
    with open("record.wav", "wb") as f:
        f.write(audio.get_raw_data())
except:
    print("録音されていません")

でテキストにできるらしいけど
そもそもマイクを認識していない?

参考サイトはwin10
Mac での動いているのを探す

Pythonで日本語を音声認識をして音声をテキスト化し、それを音声合成して発音する方法簡単解説【オウム返し by Mac その1:音声認識編】
を参考に

import speech_recognition as sr
import subprocess
import tempfile
 
 
# 音声入力
while True:
    r = sr.Recognizer()
    with sr.Microphone() as source:
        print("何かお話しして下さい。")
        audio = r.listen(source)
 
    try:
        # Google Web Speech APIで音声認識
        text = r.recognize_google(audio, language="ja-JP")
    except sr.UnknownValueError:
        print("Google Web Speech APIは音声を認識できませんでした。")
    except sr.RequestError as e:
        print("GoogleWeb Speech APIに音声認識を要求できませんでした;"
              " {0}".format(e))
    else:
        print(text)
    if text == "終わりだよ":
        break
print("完了。")

を実行したけど

Traceback (most recent call last):
  File "/Users/snowpool/test_gpt/voice_text.py", line 15, in <module>
    text = r.recognize_google(audio, language="ja-JP")
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/speech_recognition/__init__.py", line 879, in recognize_google
    flac_data = audio_data.get_flac_data(
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/speech_recognition/__init__.py", line 495, in get_flac_data
    flac_converter = get_flac_converter()
  File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/speech_recognition/__init__.py", line 1744, in get_flac_converter
    raise OSError("FLAC conversion utility not available - consider installing the FLAC command line application by running `apt-get install flac` or your operating system's equivalent")
OSError: FLAC conversion utility not available - consider installing the FLAC command line application by running `apt-get install flac` or your operating system's equivalent

となる

OSError: FLAC conversion utility not available - consider installing the FLAC command line application by running `apt-get install flac` or your operating system's equivalent

で検索したら

音声データをテキスト変換 / Speech to Text / Python
によれば
Flac が必要らしい

https://xiph.org/flac/download.html
で調べて

FLAC tools for OS X from Homebrew.
で検索
https://formulae.brew.sh/formula/flac

brew install flac

でインストール

import speech_recognition as sr

r = sr.Recognizer()
with sr.Microphone() as input:
    print("録音中:")
    audio = r.listen(input)
text = r.recognize_google(audio, language='ja-JP')
print(text)

として保存

これで再度実行すると

result2:
{   'alternative': [   {'confidence': 0.77176797, 'transcript': 'チャート GPT'},
                       {'transcript': 'チャート jpg'},
                       {'transcript': 'チャート jpt'},
                       {'transcript': 'チャート gpd'},
                       {'transcript': 'じゃあ と jpg'}],
    'final': True}
チャート GPT

となり
音声の認識とテキストにすることができた

次に

import speech_recognition as sr

r = sr.Recognizer()

with sr.Microphone(device_index=0) as source:
    print('録音中: ')
    audio = r.listen(source)

try:
    text = r.recognize_google(audio, language='ja-JP')
    print(text)

    # 録音された音声をファイルへ保存
    with open("record.wav", "wb") as f:
        f.write(audio.get_raw_data())
except:
    print("録音されていません")
を
voice_rec.py

として実行

これでマイクの音声のファイル化ができた

https://dev.classmethod.jp/articles/pyenv-command-not-found/
を参考に

brew unlink pyenv && brew link pyenv

したけど
Notebook が起動しない….

JupyterLabとJupyter Notebookの違いを簡単に解説【Mac】

https://miyukimedaka.com/2020/06/07/0143-jupyterlab-explanation/
を参考に

pip install jupyterlab


インストール

 jupyter lab

で起動

!pip install pyttsx3
import pyttsx3

engine = pyttsx3.init()
engine.say("音声読み上げライブラリ")
engine.runAndWait()

を実行したら日本語の読み上げができた