2023年5月18日木曜日

whisperを使って自動文字起こしシステムを作ってみた

 家族が録音したデータをいちいち聞いてまとめるのが大変で負担になっているということだったので、最近流行りのAIを使って文字起こしをするシステムを作ってみました。

文字起こしをしてくれるクラウドサービスなどもあるようでしたが、今回はオープンソースで使えるwhisperを使ってみました。

whisperはOpenAI社の作った自動文字起こしするためのAIで、日本語に対応した学習モデルも公開されています。

whisper + python で思ったよりもかなり簡単にできてしまったので驚いています。家族も大満足なので、おすすめです。


作ったシステムの概要

音声データをフォルダに入れておいて、定期的にサーバから音声ファイルを確認して、文字起こしがされていなければそのファイルを文字起こしして結果のテキストファイルを特定のフォルダに書き出す、というものです。

文字起こし自体はpythonで実現しました。
定期的な処理は自宅のサーバ(ubuntu)のcronで定期実行しています。
文字起こしにはそれなりに時間がかかるので、夜間に実行するようにしています。

必要なソフトウェアのインストール

以下のブログを参考にさせていただきました。

以下、前提としてpythonの環境構築はできているものとします。
今回はubuntu 20.04で実行しています。

whisperのインストール

githubに公開されているものをpipコマンドでインストールします。

$ pip install git+https://github.com/openai/whisper.git

ちょっと時間がかかります。
このインストールが完了した時点では学習モデルはダウンロードされていません。

ffmpegのインストール

今回、iphoneで録音したデータをNASに保存してもらい、その文字起こしを行いました。
iphoneの標準のアプリで録音されたデータはm4aという拡張子で、ubuntu標準ではコーデックがないようなので、ffmpegをインストールしておきます。

$ sudo apt-get install ffmpeg

Pythonスクリプト(文字起こし)

文字起こしスクリプトはpythonで実装しました。
文字起こしした結果のテキストファイルは指定のフォルダパスに、音声ファイルのファイル名の拡張子を.txtに変えたファイル名で保存するようにしています。

毎回すべての音声ファイルを文字起こしするといろいろと無駄なので、音声ファイルとテキストファイルの一覧を比較し、テキストファイル(文字起こしの結果ファイル)がないもののみ文字起こしするようにしています。

whisperの文字起こし結果は音声ファイルの時間なども含まれていますが、文字起こししたテキストのみ保存しています。

以下が最終的なファイルです。

  1. # -*- encoding:utf-8 -*-
  2. #----------------------------------------------------
  3. # auto_whisper.py
  4. #
  5. # generate trascription file from audio data.
  6. # ---------------------------------------------------
  7. import glob
  8. import os
  9. import re
  10. import whisper
  11.  
  12. # audio file types
  13. audio_types = "(m4a|mp3|wav)"
  14.  
  15. # filepath
  16. audio_folder_path = "音声ファイルのフォルダパス"
  17. text_folder_path = "出力テキストファイルのフォルダパス"
  18.  
  19. # audio file list
  20. audio_file_list = []
  21. for audio_file in glob.glob(audio_folder_path+"/*"):
  22. if re.match('.+\.'+audio_types+'$', audio_file):
  23. audio_file_list.append(audio_file)
  24.  
  25. # text file list
  26. text_file_list = []
  27. for text_file in glob.glob(text_folder_path+"/*"):
  28. if re.match('.+\.txt$', text_file):
  29. text_file_list.append(os.path.splitext(os.path.basename(text_file))[0])
  30.  
  31. # pick up audio files that have not yet been transcripted.
  32. transcript_file_list = []
  33. for audio_file in audio_file_list:
  34. if os.path.splitext(os.path.basename(audio_file))[0] in text_file_list:
  35. print(audio_file, "ari")
  36. else:
  37. print(audio_file, "nashi")
  38. transcript_file_list.append(audio_file)
  39.  
  40. # transcript files
  41. if bool(transcript_file_list):
  42. # load model
  43. model = whisper.load_model("small")
  44.  
  45. print("transcripting...")
  46.  
  47. # transcript files
  48. for transcript_file in transcript_file_list:
  49. print("trascripting: "+ transcript_file)
  50. # output file
  51. output_file_path = text_folder_path + "/" + os.path.splitext(os.path.basename(transcript_file))[0] + ".txt"
  52. f = open(output_file_path, 'w')
  53.  
  54. result = model.transcribe(transcript_file, verbose=True, language='ja')
  55.  
  56. f.write(result["text"])
  57.  
  58. f.close()
  59.  
  60. # end


定期実行

定期実行はシンプルにcronを使っています。
処理時間がかかるので夜間に実行するようにしています。


2023年2月19日日曜日

Kicad 6 で部品がSTEPファイルに出力できない場合の対応策

 Kicad 6 でSTEPファイルに出力してFusion360でインポートをよく実施するのですが、

そのときに部品がSTEPファイルにエクスポートできていない時があります。

対策として、部品の3DモデルをSTEPファイルにする必要があります。


デフォルトのライブラリではwrl形式のファイルだったりするので、その場合には対応が必要です。


デフォルトの3DモデルのフォルダにSTEPファイルも入っているので、その場合には差し替えるだけでOKです。

2021年3月6日土曜日

今更ながらRaspberry Pi Picoを触ってみる(環境構築)

Raspberry Pi は前から触っていたのですが、Raspberry Pi Picoが出たというニュースを見た時も、どうせZeroみたいに小さくなっただけでしょと思い込んであまり興味がありませんでした。

よくよく調べてみると、これまでのRaspberry Piとは異なりベアメタルで使用することが前提ということが分かり、マイコン好きとしては断然興味が湧いてきました。



 ということでまずは開発環境の構築をしてみます。

2020年10月23日金曜日

宅内LAN配線してIPv6とIPv4を両立してVPNサーバを立ててみた

今年の秋についに一軒家を購入したので、家庭内のLANを構築しなおしました。
備忘録を兼ねてゼロからLANケーブルを壁内配線してネットワークを構築するまでをまとめます。

やっぱり高速なIPv6(IPoE)で有線LANを引き回したいし、VPNもつなぎたい

宅内でLANを引き回すからにはなるべく高速で快適な環境を作りたいですね。
インターネットの接続はPPPoE方式ではなくIPoE方式とします。
IPoE方式などはこちらが参考になりました。

IPoE方式についていろいろ調べてみると、サーバの公開やVPNサーバがそのままではできないことが分かり、先人たちが二重ルータにしたりいろいろ試行錯誤されていることも分かりました。
要はIPv4ネットワークとIPv6ネットワークを共存させれば何とかなりそうです。
今回はIPoEオプションが2020年1月から無料になったということでIIJのmioひかりを契約しました。

有線を宅内に配線する

インターネットへの接続方法が決まったところで、宅内に有線LANを張り巡らせる方法を考えます。
壁内に配線管(CB管)をあらかじめ用意しておき、そこにLANケーブルを通すのが理想的ですが、私が購入した家はそのような配線管はありません。
そうなるとLANケーブルを引き回すには部屋の中にモールを設置してそのモールの中をLANケーブルを通すか、どうにかして壁内を引き回す必要があります。
モールは簡単でよいのですが、見栄えが良くありません。
ということで、大変そうですが壁内にLANケーブルを通すことにしました。

住宅の構造がどうなっているのか調べてみた

今回LANケーブルを引き回す我が家はいわゆる在来工法(木造軸組構法)です。
在来工法は木で柱と梁で構造をつくり、そこに壁を張っていきます。
梁の両側に壁を張るため、壁と壁の間にスペースができます。そのままでは断熱効果が弱いので断熱材をこの壁の間に敷き詰める構造になっています。
上から見た断面図はこんな感じです。

今回、この壁と断熱材の間にLANケーブルを通していきます。

我が家はロフトのような屋根裏収納があり、そこから点検口を通じて屋根裏に入ることができます。
この屋根裏収納を簡易サーバルーム(夏は暑いのであまりよくないですが...)にするため、屋根裏と各部屋にLANケーブルを配線します。
LANケーブルはコンセントに接続口を設ける形にします。

屋根裏から壁の中へ通線ワイヤを通す

壁内を通すといっても、壁の中へ入ったりすることはできないので、何らかの方法で屋根裏からコンセントまでLANケーブルを通す必要があります。
今回は通線ワイヤを用意して作業することにしました。壁の中を通すためになるべくスリムなものをということで、ジェフコムのDENSAN BX4030Jを用意しました。
ケース付きでお買い得です。



作戦としては、屋根裏からコンセントにつながる電力線(VVFケーブル)を探し、その電力線伝いに通線ワイヤを壁の中に通していきます。
屋根裏はこんな感じでした。下に見えている白いものが断熱材です。断熱材の下は天井なので、体重をかけたら天井が抜けて下に落ちます。柱の上を通って電力線を辿っていきますが、柱と柱の間隔が空いているところがあるので、近所のホームセンターで2×10の木材を買ってきて足場にしました。


通線前にあらかじめコンセントのふた(?)を開けておきます。
天井裏から壁の中に通線ワイヤを通し、ワイヤの先が目的のコンセントまで到達したら、その先にLANケーブルを取り付けて屋根裏に引っ張り上げて作業完了です。
ワイヤの先が目的のコンセントにうまくいくかは運次第です。何度もワイヤを出し入れしてようやく目的のコンセントまで届きました。


ここまでくれば後は通線ワイヤの先にLANケーブルを括り付けて天井裏に引っ張り上げるだけです。
これを繰り返して必要な部屋にLANケーブルを配線しました。

コンセントのLANケーブルの接続口はぐっどすを使いました。
LANケーブルのコネクタは結構つけるのが大変なイメージがありましたが、工具もいらず楽ちんです。
こんな感じでLANケーブルの口を取り付けることができました。


CD管を通しているわけではないので、交換することはしばらくないだろうと思い贅沢にCAT6のケーブルを通しました。

外からVPNでつなげるようIPv4を共存させる

さて、物理的な接続ができたところで宅外からつなぐ用のIPv4とインターネットに高速に接続するためのIPv6を共存させる方法を考えます。
以前やっていたように、外部にVPNサーバを立てて家庭内のサーバからブリッジを張るという方法もあり、これでもうまくいきそうな気がしましたが、なんだか複雑になってしまいそうなので、なるべくシンプルにしたいところです。

いろいろ調べてみると、以下の記事が見つかりました。

これはいいなということで、こちらの記事を参考にネットワークを構築することにしました。

VPNがつながらない

ubuntuマシンにSoftether VPNサーバを立てて、ルータの設定をしてみました。
構成は以下のような感じです。



上記の記事にあるようにルータ側の設定でVPNサーバからの通信はIPoEではなくPPPoEで接続するように設定してあげます。
こうすることでVPNサーバからの通信はPPPoEによるIPv4接続、ほかのPCやスマートフォンからの接続はIPv6接続できるようです。

しかし、LAN内部から外部にIPv6で出ていくことはできるのですが、外部からVPNサーバへの接続ができません。
ためしにルータの接続方式をPPPoE(IPv4)に変えると外部からVPN接続できました。
どうやらVPNサーバ自体は正常に動いているようです。
ルータの設定を色々変えて試してみましたが、結局IPoEにして外部からVPNサーバへ接続することはできませんでした。
何日か悩んで結局うまくいかず諦めました。

二重ルータにしてみる

ルータを一台の構成は諦めて、ルータを2台使用する方法を試してみました。
構成はこんな感じです。


ルータ1はIPoEで接続するルータで、PPPoEパススルー(Baffuloはこういう設定名のようです。PPPoEブリッジとか呼ばれる場合もあるようです)設定しておきます。
もう一台のルータ2PPPoEで接続するルータです。
また、この2台のルータのLAN側を接続して同じLANセグメントとしておきます。
(この時、片方のDHCPサーバ機能はOFFにする必要があります)
ルータ1,2どちらをデフォルトゲートウェイに設定するかでIPv4ネットワークに繋ぐか、IPv6ネットワークに接続するかを選択できます。

この構成で試してみたところ、やはり外部からVPNで接続することができませんでした。
今回はIPv4の方は固定IPではないためDDNSを使用する方法にしていましたが、どうやらIPv4のDDNSサーバにアクセスができていないようでした。

IPv6用のルータ1の設定をPPPoE(IPv4)にすると正常に接続できるので、おそらくIPv4用のルータ2でに出て行くことができていないと思われます。

ONUからスイッチングハブでIPv4とIPv6用のルータで分けてみる

ルータを2台でPPPoEパススルーを使用する構成はうまくいかなかったため、ONUからの配線をスイッチングハブで2台のルータにそれぞれ分ける方法をとってみました。

構成は以下の感じです。

先ほどとの違いは、ルータ1はPPPoEパススルー機能が必要ないということです。
ルータ1,2のWAN側はスイッチングハブ(HUB)に、ルータ1,2のLAN側をそれぞれ接続して同じセグメントにしておきます。

この構成にしても、二重ルータにする方法と同じ結果で、デフォルトゲートウェイをIPv4側にしてもIPv6で接続しているようでした。
いろいろルータの設定をいじりながら悩みましたが、結果的にIPv6側のルータで送信元のIPがVPNサーバのものは全て無視するようにパケットフィルタリングの設定をしたところ、無事にVPN接続ができるようになりました。
おそらくVPNサーバからDDNSサーバにパケットを送るときにIPv6側のルータを通ってしまっていたためと思われます。(ルーティングの問題?)

VPNサーバ自体でPPPoE接続してみた

何とかルータ2台とスイッチングハブを使用して目的は達成できましたが、外からVPNサーバに接続するためだけにルータを一台用意するのはあまりスマートとは言えないですね。
どうにかもっとシンプルにできないかと考えていたところ、PPPoEで接続するためにルータを用意するのであれば、VPNサーバ自体がPPPoEで接続すれば良いのではと思いつきました。
調べてみるとRaspberry Pi 4で同じようなことをやっている方がいました。

こちらの記事を参考にさせていただきました。
(ほとんど丸ごとコピペです)

最終的な構成は以下のようになりました。結局、最終的に考えていた構成と同じでかなりシンプルです。



VPNサーバにpppoeとpppoeconfをインストールして、PPPoE接続している時のデフォルトルートを変更しておきます。忘れずにルータのPPPoEパススルーも有効にしておきます。
VPNサーバに直接グローバルIPが割り振られることになるのでファイヤーウォールの設定もしておく必要があります。今回はVPN接続に必要なポートと、SSH用のポートのみ開放としておきました。

おうちネットワークは楽しい

引越しを機に久しぶりにネットワークの構築を行ってみました。
LANケーブルの引き回しやIPv6についてなど、初めてのことが沢山ありますとても勉強になりました。何より自分で何かを作っていくのは楽しいですね。

2020年1月4日土曜日

M5Balaのサンプルプログラムを動かすまでの顛末

あけましておめでとうございます。

本業のほうがかなり忙しく、年末まで個人的な開発はほとんどできない状況でした。
今年の年末年始はM5Balaを買ったのでこれを題材に制御のお勉強をしたいと思います。
M5Stack自体は以前から触ってはいたのですが、今回は本格的に開発したいということでPlatformIOの開発環境を整えてM5Balaのサンプルプログラムを動かしてみます。
この過程でかなりはまった点があり、これについても記載します。


2019年9月16日月曜日

技術書典7おしながき

9月22日に開催される技術書典7にサークル「おこめやエレクトロニクス」として参加します!

技術書典7では新刊「乾電池2本で光らせるニキシー管電源の製作 低入力電圧へのアプロ―チ」のほか、既刊「ニキシー管電源設計入門 ニキシー管時計の設計と製作」「ニキシー管電源設計実践 回路シミュレーションとAnalog Discoveryの活用」を頒布します。

3冊連続でニキシー管の電源に関する本ですが、今回の新刊は低入力電圧化に焦点を当てたものになっています。
もともとはバッテリ駆動でいろいろ工作したいなーということで始めた要素技術開発的な位置づけでした。そのうち今回の新刊で紹介した電源回路を使ったものを作りたいと考えています。
 

実際に乾電池2本でニキシー管を光らせる様子も展示できたらいいなぁと考えています。
ニキシー管時計も二種類展示する予定ですので、ぜひ9/22 2F展示ホールD す25D に遊びに来てください。

https://techbookfest.org/event/tbf07/circle/5688815574319104

以下、おしながきです。

2019年5月23日木曜日

またニキシー管時計を作ったお話

昨年の技術書典5でニキシー管時計の事例を紹介していましたが、いろいろ満足できていない箇所があったので改めてニキシー管時計を作りました。

某オークションでニキシー管を探していると、B-5853というJRCのニキシー管が手ごろな値段でありましたので、このニキシー管を使用することにしました。
このB-5853はニキシー管の中でも小型な部類に入るニキシー管でしたので、なるべくコンパクトにすることを目指すことにしました。