speech to textを作ってみる2(Python)

 

前回からの続きです。

 

ソースプログラムはGithubに置いてありますので、

 

https://github.com/genestera-jp/speech_to_text

 

の中のSpeech_textmain.pyまたは、前回の記事を参考に見てください。

 

(行番号41から47)

        #言語選択スピンボックスボタン
        self.v = ('ja-JP_BroadbandModel','en-US_BroadbandModel','en-GB_BroadbandModel')
        self.SpinBox1 = tk.Spinbox(value = self.v,width = 25,state = 'readonly')
        self.SpinBox1.grid(row=3,column=0,pady=10)
        #テキスト出力ボタン
        self.Button5 = tk.Button(text=u'テキスト出力',width=20,command=self.button_clicktx)
        self.Button5.grid(row=3,column=1,pady=10)

 

の部分については、

 

スピンボックスは日本語と英語及び米語を切り替えるために使います。

(あと、

アラビア語 'ar-AR_BroadbandModel'

スペイン語 'es-ES_BroadbandModel'

フランス語 'fr-FR_BroadbandModel'

ブラジル語 'pt-BR_BroadbandModel'

韓国語   'ko-KR_BroadbandModel'

ドイツ語  'de-DE_BroadbandModel'

中国語   'zh-CN_BroadbandModel'

が使えますので、

self.v = ('ja-JP_BroadbandModel','en-US_BroadbandModel','en-GB_BroadbandModel')

に随時追加してください)

テキスト出力ボタンを新たにつくります。クリックされた時の処理は以下になります。

 

 

(行番号86から99)

    #テキスト変換処理
    def button_clicktx(self):
        lang_k = self.SpinBox1.get()
        speech_text2.text_json(self.file_na,lang_k)
        self.Scrolltext1.delete('1.0', 'end')
        with open("result.json","r") as f:
            self.result_json = json.load(f)
        for i in range(len(self.result_json["results"])):
            self.cmd = self.result_json["results"][i]["alternatives"][0]["transcript"]
            if lang_k == "ja-JP_BroadbandModel":
                self.cmd = self.cmd.replace(' ','')
            if lang_k == "en-US_BroadbandModel":
                self.cmd = self.cmd.replace('%HESITATION ','')
            self.Scrolltext1.insert('end',self.cmd + '¥n')

 

の部分については、

speech_text2.text_json(self.file_na,lang_k)

でimportされたspeech_text2を実施し、

保存された、

        with open("result.json","r") as f:
            self.result_json = json.load(f)

jsonファイルを呼び込んで、

前回説明した#表示部分を関数にしたものです。

説明については前回行っていますので、省略します。

なお、

            if lang_k == "en-US_BroadbandModel":
                self.cmd = self.cmd.replace('%HESITATION ','')

で米語で、「あー」とか「うー」を意味する'%HESITATION 'を取り除いています。

 

なお、前回説明したように、

speech_text2.pyには必ず、ユーザー名、パスワードを入れておかないと動きません。

 

 

実行例:今回は、ユーチューブから英語のものを録音してテキスト出力してみました。

 

 

英語の変換は、ほぼ完璧でした。

なので、英語に変換したものを見ながら、録音したもの聞けば、

英語のリスニング勉強にもなります。

もしくは、自分で発音したものを録音して、正確に変換されるようなら、

外国人にもネイティブに聞こえていることになります。

ただ、通信状況にもよりますが、(音声ファイル1分で)40秒ほどかかります。

なお、送信できる音声ファイルは最大100Mbまでです。

 

(変換状況が見たい場合は、)

もうひとつの方法として、

Watsonには、ウェーブソケット(Websocket)のインターフェースを使って接続できます。

ウェーブソケットとは、HTTP方式とは違って、常時接続状態にできる通信方法です。

 

せっかくですので、参考にサンプル('out1.wav'ファイルを変換)を載せておきます。

(Watsonのリファレンスを参考しています。

ソースプログラムはこのブログの最初のGithubにあるspeech_text_websocketです。)

 

from watson_developer_cloud import SpeechToTextV1
from watson_developer_cloud.websocket import RecognizeCallback, AudioSource
from os.path import join, dirname
import json

speech_to_text = SpeechToTextV1(
    username='ユーザー名',
    password='パスワード')

class MyRecognizeCallback(RecognizeCallback):
    def __init__(self):
        RecognizeCallback.__init__(self)

    def on_connected(self):
        print('Connection was successful')

    def on_data(self, data):
        print(json.dumps(data, indent=2))

    def on_error(self, error):
        print('Error received: {}'.format(error))

    def on_inactivity_timeout(self, error):
        print('Inactivity timeout: {}'.format(error))

myRecognizeCallback = MyRecognizeCallback()

with open('out1.wav','rb') as audio_file:
    audio_source = AudioSource(audio_file)
    speech_to_text.recognize_using_websocket(
        audio=audio_source,
        content_type='audio/wav',
        recognize_callback=myRecognizeCallback,
        interim_results=True,
        model='en-US_BroadbandModel',)

コピーアンドペーストするときは、段落にが崩れますので、貼り付け後修正してください。

 

概要:Websocketで接続して、結果をコールバックでその都度表示しています。

 

実行すると、順次結果がプリントされます。

ですが、その都度変換をしているので、結果として、HTTP方式の方が早くなりました。

(全体で2分くらいかかります。)

 

なお、

watson_developer_cloudは頻繫にアップグレードされているようで、

Windowsでは、PowerShellなどで、

 

 py -m  pip install --upgrade watson-developer-cloud

 

を実行して最新のものでないとバージョンの関係で動かない場合があります。

 

最後に、これまでのものは、説明用なので、アプリとして人前で使うときは、

恥ずかしいのでGithubのSpeech_textmain_v1.pyを使ってください。

(ボタンを減らして、メニューバーにしてあるバージョンです。textを保存できます。)

 

ソフトウェアを開発するうえで、

無料でクラウドサービスを提供してくれているIBMさまに感謝いたします。

(もちろんMicrosoftさまにもVisual Studio,Visual Code,Githubでお世話になっております。)

 

 

次回はまだ考えていませんが、せっかくIBMクラウド環境があるので、

まだこのブログではやっていないNode.jsを使ってみたいとおもいます。

 

次回Webアプリを作ってみる

 

| python | 10:26 | comments(0) | trackbacks(0) |

speech to textを作ってみる(Python)

 

前回からの続きです。

 

前回までで、録音のプログラムはできました。

あとは、IBMのWatson、Speech to Textを使って音声を文字に変えるだけです。

googleのAPIのSpeech to Textでもできますが、どうもWatsonの方が簡単そうです。

 

参考:あぱーブログ様(GoogleとIBM Watsonの音声認識APIを比較してみた)

 

IBMのWatsonについては、

まえにワトソンの翻訳AIを使ってみる

で翻訳プログラムを作っていますので、登録については、

ブログ内のアカウント作成手順などについて参考にしてください。

無料アカウントで制限はありますが、クレジットカードを登録することなく安心です。

また、importするwatson_developer_cloudはpipでダウンロードしておいてください。

 

実は下のデモを使えばプログラムを作る必要もない気がしますが

 

WatsonのSpeech to Textのデモ

 

勉強のためには自分で作るものいいものです。

 

プログラム自体は実に簡単にできます。

まず、音声ファイルをテキストにするだけのプログラムを作ってみます。

仕様:'out1.wav'を日本語に変換します。

from watson_developer_cloud import SpeechToTextV1
import json

user=''ユーザー名"
pswd=''パスワード"
audio_file = open("out1.wav", "rb")
cont_type = "audio/wav"
lang = "ja-JP_BroadbandModel"

# ワトソンとの送信と受信
stt = SpeechToTextV1(username=user, password=pswd)
result_json = stt.recognize(audio=audio_file, content_type=cont_type, model=lang).get_result()

# 表示

for i in range(len(result_json["results"])):

    result_p = result_json["results"][i]["alternatives"][0]["transcript"]
    if lang == "ja-JP_BroadbandModel":
        result_p = result_p.replace(' ','')
    print(result_p)

# ファイルの保存

with open("result.json","w") as f:
    json.dump(result_json,f,ensure_ascii=False,indent=2)

# 終了
input(u"終了しますか?")

解説:

まず、ユーザー名とパスワードは自分のものに変えてください。

細かいことは、watson_developer_cloudが全部やってくれます。

stt = SpeechToTextV1(username=user, password=pswd)でワトソンと接続して

result_json = stt.recognize(audio=audio_file, content_type=cont_type, model=lang).get_result()

でオーディオファイルを送るとJson形式で答えが返ってきます。

たったこれだけです。

 

たとえば、音声が英語(米語)の場合は、

lang = "ja-JP_BroadbandModel"をlang = "en-US_BroadbandModel"にします。

 

for i in range(len(result_json["results"])):
    print(result_json["results"][i]["alternatives"][0]["transcript"])

 

プリントは"results"の数("alternatives")だけ結果("transcript")を印字します。

日本語については、result_p = result_p.replace(' ','')で空白を消しています。

 

with open("result.json","w") as f:
    json.dump(result_json,f,ensure_ascii=False,indent=2)

 

'result.json'という名前でファイルに保存します。

 

実行結果(例):経済番組を録音して、試してみました。

 

見ての通り、正確性は90%ぐらい?でしょうか

日本語というのは、機械にとってはいかに曖昧な言葉かがわかります。(同音異義語が多いため)

(主観では英語については、95%ぐらいの正確性があります。)

 

ここまでくれば、あとは、前につくった録音プログラムに組み込むだけです。

全体の約90%は完成です。

 

まず、上のプログラムを関数にして、本プログラムでimportできるようにします。

 

from watson_developer_cloud import SpeechToTextV1
import sys,os.path
import json

def text_json(out_f="out1.wav",lang_k="ja-JP_BroadbandModel"):
    user='ユーザー名'
    pswd='パスワード'
    audio_file = open(out_f, "rb")
    ext = os.path.splitext(out_f)[1][1:]
    cont_type = "audio/" + ext
    print (cont_type)
    lang = lang_k
    # ワトソンとの送信と受信
    stt = SpeechToTextV1(username=user, password=pswd)
    result_json = stt.recognize(
            audio=audio_file,
            content_type=cont_type,
            model=lang).get_result()
    # ファイルの保存
    with open("result.json","w") as f:
        json.dump(result_json,f,ensure_ascii=False,indent=2)

Wavファイル以外でも動作するように、引数から

音声データのタイプを拡張子を取り出して、

ext = os.path.splitext(out_f)[1][1:]

cont_type = "audio/" + ext

ように変更します。(import sys,os.pathも忘れずに)

 

#表示の部分は必要ないので削除します。

 

名前を付けて保存します。

今回は、Speech_text2.pyとしてメインプログラムと同じフォルダに保存します。

 

メインプログラム(speech_textmain.py)は、

import tkinter as tk
import tkinter.scrolledtext as st
import tkinter.filedialog as flog
import sys,os.path
import subprocess
import wave
import speech_text2
import json

class Application(tk.Frame):
    def __init__(self, master=None,file_name='out.wav'):
        super().__init__(master)
        self.grid()
        self.create_widgets()
        self.master.title(u"Speech to Text アプリ")
        self.master.geometry("640x512")
        self.cmd = ""
        self.file_na = file_name
        self.p = None
        self.rec_flag = False
        self.master.protocol("WM_DELETE_WINDOW", self.on_closing)
        self.result = {}
        self.result_json = {}

        self.lang_k = ""

    def create_widgets(self):
        #録音開始ボタン
        self.Button1 = tk.Button(text=u'録音開始ボタン',width=20,command=self.button_clickrec)
        self.Button1.grid(row=0,column=0,pady=20)
        #録音停止ボタン
        self.Button2 = tk.Button(text=u'録音停止ボタン',width=20,command=self.button_clickstop)
        self.Button2.grid(row=0,column=1,pady=5)
        #再生ボタン
        self.Button3 = tk.Button(text=u'再生ボタン',width=20,command=self.button_clickplay)
        self.Button3.grid(row=1,column=0,pady=5)
        #出力ファイル変更ボタン
        self.Button4 = tk.Button(text=u'出力ファイルの変更',width=20,command=self.button_clickfc)
        self.Button4.grid(row=1,column=1,pady=5)
        #スクロールテキスト
        self.Scrolltext1 = st.ScrolledText()
        self.Scrolltext1.grid(row=2,columnspan=2,padx=20,pady=20)
        #言語選択スピンボックスボタン
        self.v = ('ja-JP_BroadbandModel','en-US_BroadbandModel','en-GB_BroadbandModel')
        self.SpinBox1 = tk.Spinbox(value = self.v,width = 25,state = 'readonly')
        self.SpinBox1.grid(row=3,column=0,pady=10)
        #テキスト出力ボタン
        self.Button5 = tk.Button(text=u'テキスト出力',width=20,command=self.button_clicktx)
        self.Button5.grid(row=3,column=1,pady=10)

    #録音開始
    def button_clickrec(self):
        if self.rec_flag == False:
            self.cmd = "sox -t waveaudio -d "+ self.file_na
            self.p = subprocess.Popen(self.cmd.split())
            self.Scrolltext1.insert('end',u'録音を開始しました¥n')
            self.rec_flag = True

    #録音停止
    def button_clickstop(self):
        if self.rec_flag == True:
            self.p.terminate()
            self.Scrolltext1.insert('end',u'録音を終了しました¥n')
            try:
                self.p.wait(timeout=1)
                self.rec_flag = False
            except subprocess.TimeoutExpired:
                self.p.kill()
                self.rec_flag = False

    #再生
    def button_clickplay(self):
        if self.rec_flag == False:
            self.cmd = self.file_na + '¥n'
            self.p = subprocess.call(self.cmd,shell=True)
            self.Scrolltext1.insert('end',u'再生を実行中。ファイル名:' + self.cmd)

    #出力ファイル名変更
    def button_clickfc(self):
        self.file_na = flog.asksaveasfilename()
        self.Scrolltext1.insert('end',u'出力ファイル名変更:' + self.file_na + '¥n')

    #録音中に終了したときの処理
    def on_closing(self):
        self.button_clickstop()
        sys.exit()

    #テキスト変換処理
    def button_clicktx(self):
        self.lang_k = self.SpinBox1.get()
        speech_text2.text_json(self.file_na,self.lang_k)
        self.Scrolltext1.delete('1.0', 'end')
        with open("result.json","r") as f:
            self.result_json = json.load(f)
        for i in range(len(self.result_json["results"])):
            self.cmd = self.result_json["results"][i]["alternatives"][0]["transcript"]
            if self.lang_k == "ja-JP_BroadbandModel":
                self.cmd = self.cmd.replace(' ','')
            if self.lang_k == "en-US_BroadbandModel":
                self.cmd = self.cmd.replace('%HESITATION ','')
            self.Scrolltext1.insert('end',self.cmd + '¥n')

#本体
if __name__ == '__main__':
    root = tk.Tk()
    app = Application(master=root,file_name='out1.wav')
    app.mainloop()

です。

前回のプログラムのうち青い部分が今回変更、追加した場所です。

これでとりあえず、完成です。

 

ソースプログラムはGithubに置いておきました。

 

https://github.com/genestera-jp/speech_to_text

 

 

長くなりましたので、ちょっと休憩しましょう。

解説は次回にします。

 

昔は、総務の仕事もしたことがあり、会議の議事録をつくるのが、大変だったです。

そのころは、偉い教授先生に了解をとるため、一字一句書き起こしていました。

そのころに、こんなアプリが作れていれば助かっていたと思います。

 

 

次回に続く

 

 

JUGEMテーマ:プログラミング

 

 

| python | 11:13 | comments(0) | trackbacks(0) |

音声を録音してみる2(Python) SoX(Sound exchenge)

 

前回からの続きです。

 

いつもどおり、tkinterを使ってGUIにしてみたいと思います。

あまり機能を付けすぎるとプログラムが分かりにくくなりますので、最低限の機能、チェックしかありません。

 

仕様:

録音開始ボタンで録音開始する。

録音停止ボタンで録音を終了する。

再生ボタンでWindows既定のソフトで再生する。

出力ファイルの変更で音声出力ファイルを変更できるようにする。

 

実行した例:

 

 

 

 

ソースプログラムです。

 

import tkinter as tk
import tkinter.scrolledtext as st
import tkinter.filedialog as flog
import sys,os.path
import subprocess
import wave

class Application(tk.Frame):
    def __init__(self, master=None,file_name='out.wav'):
        super().__init__(master)
        self.grid()
        self.create_widgets()
        master.title(u"録音アプリ")
        master.geometry("640x512")
        self.cmd = ""
        self.file_na = file_name
        self.p = None
        self.rec_flag = False
        master.protocol("WM_DELETE_WINDOW", self.on_closing)

    def create_widgets(self):
        #録音開始ボタン
        self.Button1 = tk.Button(text=u'録音開始ボタン',width=20,command=self.button_clickrec)
        self.Button1.grid(row=0,column=0,pady=20)
        #録音停止ボタン
        self.Button2 = tk.Button(text=u'録音停止ボタン',width=20,command=self.button_clickstop)
        self.Button2.grid(row=0,column=1,pady=5)
        #再生ボタン
        self.Button3 = tk.Button(text=u'再生ボタン',width=20,command=self.button_clickplay)
        self.Button3.grid(row=1,column=0,pady=5)
        #出力ファイル変更ボタン
        self.Button4 = tk.Button(text=u'出力ファイルの変更',width=20,command=self.button_clickfc)
        self.Button4.grid(row=1,column=1,pady=5)
        #スクロールテキスト
        self.Scrolltext1 = st.ScrolledText()
        self.Scrolltext1.grid(row=2,columnspan=2,padx=20,pady=20)

    #録音開始
    def button_clickrec(self):
        if self.rec_flag == False:
            self.cmd = "sox -t waveaudio -d "+ self.file_na
            self.p = subprocess.Popen(self.cmd.split())
            self.Scrolltext1.insert('end',u'録音を開始しました¥n')
            self.rec_flag = True

    #録音停止
    def button_clickstop(self):
        if self.rec_flag == True:
            self.p.terminate()
            self.Scrolltext1.insert('end',u'録音を終了しました¥n')
            try:
                self.p.wait(timeout=1)
                self.rec_flag = False
            except subprocess.TimeoutExpired:
                self.p.kill()
                self.rec_flag = False

    #再生
    def button_clickplay(self):
        if self.rec_flag == False:
            self.cmd = self.file_na + '¥n'
            self.p = subprocess.call(self.cmd,shell=True)
            self.Scrolltext1.insert('end',u'再生を実行中。ファイル名:' + self.cmd)

    #出力ファイル名変更
    def button_clickfc(self):
        self.file_na = flog.asksaveasfilename()
        self.Scrolltext1.insert('end',u'出力ファイル名変更:' + self.file_na + '¥n')

    #録音中に終了したときの処理
    def on_closing(self):
        self.button_clickstop()
        sys.exit()

#本体
if __name__ == '__main__':
    root = tk.Tk()
    app = Application(master=root,file_name='out1.wav')
    app.mainloop()

 

なお、このソースプログラムはGithubの

 

https://github.com/genestera-jp/speech_to_text

 

の rokuon_tkinter.py に置いてあります。

ダウンロードのしかたは前の記事を参考にしてください。

 

 

解説:(ピンポイント)

 

基本的に前回のプログラムをtkinterでGUIしただけです。

self.rec_flag = Falseで録音中(true)かどうかの判定をしています。

また、

master.protocol("WM_DELETE_WINDOW", self.on_closing)で

ウィンドウが閉じられたときの処理ですが、

これは、subprocess.Popenで起動したプログラムが親プログラムを終了しても

終了せず、バックグラウンドで実行されてしまうからです。

たとえば、録音中に×印でプログラムを終了してもバックグラウンドではSoXのプログラムは

実行され続けて、録音され続けることを防ぐためです。

(もし、ここでプログラムミスをした場合は、タスクマネージャーでSoXを強制終了してください)

 

#スクロールテキストで

今回は、結果の表示にテキストではなくtkinterのスクロールテキストを使っています。

self.Scrolltext1 = st.ScrolledText()

これは、speech to Textのプログラムを作る上での準備です。

 

#録音開始で

soxのコマンド

self.cmd = "sox -t waveaudio -d "+ self.file_na

で、サンプルレート(-r)やビットレート(-b)を変えたい場合は、(Windowsはデフォルトは-r 48000)

例)self.cmd = "sox -t waveaudio -r 44100 -b 16 -d " + self.file_na

のように変えてください。

 

#再生で

再生ボタンで、subprocess.call(self.cmd,shell=True)により、

Windowsで設定されたプレイヤーで再生します。(この場合、shell=Trueを付けないと動きません。)

 

#出力ファイル名変更で

出力ファイルの変更で、音声ファイルの出力先を自由に変更します。

ここでは拡張子は指定していないので、拡張子まで間違えなく入力してください。

 

#本体で

app = Application(master=root,file_name='out1.wav')

デフォルトの保存先は、カレントディレクトリ(プログラムを実行した場所)の'out1.wav'です。

(メモリーを節約したい場合は、前回の説明に従って'out1.mp3'でMP3にすることもできます。

ただし、おすすめは、容量半分で劣化のないFlac形式'out1.flac'ですが)

 

 

次回は、今回録音したものを、Watson API Speech to Textを使って文字変換したいと思います。

 

 

次回に続く

 

 

| python | 17:20 | comments(0) | trackbacks(0) |

音声を録音してみる(Python)SoX(Sound exchenge)

 

パソコンで音声を録音する方法はいろいろあります。

Pythonでは、pyaudioを使うのが一般的ですが、設定を多くしなければなりません。

ところが、前に、画像処理にFFMPEGを使ったように、

音声専門のプログラム(Sox)を使用すると引数を渡すだけで簡単に録音できます。

無理にPythonだけでプログラムする必要はありませんし、ほかの言語

C++やC#などのプログラムを使っても、単純化できます。

 

また、Pythonを使わずフリーソフトでよければ、Audacityなどを使えば録音、編集できます。

 

まずは、SoXをダウンロードします。

 

SoX-SoundexchengeのホームページからDownloadに進んで

 

 

Windowsの場合は、sox-14.4.2-win32をダウンロードします。

sox-14.4.2-win32.exeの場合はインストーラが自動的に立ち上がりインストールされます。

 

Windowsでは、デフォルトで,C:¥Program Files (x86)¥sox-14-4-2に入ります。

ですが、Pathは通っていませんので、Path を通しておきます。

よく使うので知っているとは思いますが、忘れやすいので簡単に説明しておきます。

エクスプローラからPCを選んで、右クリック

 

 

プロパティを選んで、コントロールパネルから

 

 

システムの詳細設定をクリックします。

システムのプロパティが表示されるので、

 

 

環境変数(N)をクリックします。

ユーザー環境変数のPathを選んで、編集を選びます。

(システム全体(個人のパソコンの場合)にPathを通したい場合は、ユーザー環境変数ではなく

下にあるシステム環境変数(S)のPathを選んでください。

その場合はユーザー環境変数を変更する必要はありません)

 

 

今回は、ユーザーの環境変数のPathを通しています。

新規(N)からダウンロードされたPathを入力して、OKボタンを押します。

 

 

これで、どこからでもSoXプログラムを起動できます。

(Windowsが、システム環境変数プラス、ユーザー環境変数を呼び込みます。)

 

前置きは長かったですが、プログラムは簡単です。

下のプログラムを実行すると、Enterキーを押すまで"out.wav"にWindows上の音が録音されます。

import subprocess
import wave

print("Start recording...")
cmd = "sox -t waveaudio -d out.wav"
p = subprocess.Popen(cmd.split())

input("Enter to stop: ")
p.terminate()
try:
    p.wait(timeout=1)
except subprocess.TimeoutExpired:
    p.kill()

説明:(SoXはC言語でコマンドラインで使用します。)

cmd変数はコマンドラインの内容です。

-t がオーディオのタイプでwaveaudioの-dがデバイスで入力しout.wavに出力します。

(Windowsの場合のみ、データフォーマットの"-t waveaudio"(おそらくマイク入力)を指定します。

-t waveaudio 1 はおそらくライン入力?)

p = subprocess.Popen(cmd.split())

コマンドラインを実行するときは、subprocessを使います。

split()で空白ごとに区切って使います。

Popenは、pythonでの実行と関係なく実行します。

p.terminate()で子プロセスの終了を通知します。

try:
    p.wait(timeout=1)
except subprocess.TimeoutExpired:
    p.kill()

で子プロセスの終了を1秒待ちます。

もしタイムアウトが発生したら子プロセスを消します。

 

なお、SoXの説明では、Windowsでは、sox.exeコマンドをコピーして

play.exeとrec.exeとsoxi.exeという名前で保存すれば、Unixと同じように使えるとのことです。なので、

cmd = "rec -t waveaudio -d out.wav"

とすることができます。(あたりまえですが)

 

なお、MP3ファイルのエンコード、デコードは著作権の関係で入っていませんので、MP3が好きなひとは

エンコード(録音):libmp3lame-0.dll

デコード:(再生):libmad-0.dll

app.box.comからダウンロードして、sox14-4-2のフォルダにコピーしてください。

(ただし、圧縮ファイルがZIPではなく7zファイルになっています。

7z解凍ソフト(Web上にもサービスがあります。)などで解凍してください。)

 

最終的には、Speech to Text(議事録作成)のプログラムを作成する予定です。

(近頃は、中央官庁では都合の悪いものは作成していないことになっている!?そうですが

前勤めていた下部組織の国立大学法人では必ず作っていました。)

 

 

次回につづきます。

 

 

JUGEMテーマ:プログラミング

| python | 08:58 | comments(0) | trackbacks(0) |

簡単なデータ処理のひな形(Python)

 

プログラムは、基本となるひな形(プロトタイプ)を作っておくと、

なんでも応用がきくようになります。

それをもとに修正すれば、非常に効率的です。(いま流行の生産性がよい)

 

ここでは、pythonでデータ処理のひな形を作ってみました。

具体的には、パスワードの管理プログラムです。

でも、名前を変えれば、住所録にも、社員名簿、物品管理簿などにも変わります。

また、ローカル環境のPythonのプログラミングの基本も入れたつもりです。

 

仕様:

入力ボタンでリストボックスに追加

クリアボタンで入力フィールドをクリア

保存ボタンでファイルに保存

呼込ボタンでファイルから呼び込み

リストボックスをダブルクリックで内容を表示、パスワードをクリップボードにコピー

(サイトですぐに貼り付けができるように)

リストボックスで削除したい項目をクリックしてDelキーで削除

リストボックスで挿入したい場所をクリックしてshift+Delキーで挿入

パスワード作成ボタンでPasswordのフィールドにパスワードを自動作成

以上の作業状況を表示

 

実行例:

 

 

ソースプログラムは、前回作ったGithubに置いてありますので、

 

https://github.com/genestera-jp/password_manage

 

からダウンロードしてください。

 

ダウンロードは、Clone or downloadからDownload ZIPで行えます。

 

 

ダウンロードしたものを、解凍(ZIPを)してpassword_main.pyを実行してください。

(随時更新していますので、バージョンなどは変わります。)

 

解説(ピンポイントです。):GithubのPassword_main.pyを見ながら読んでください。

行番号は、上のGithub上でpassword_main.pyをクリックしてプラウザで表示した番号です。

 

3行目から7行目

import sys
import tkinter as tk
import pickle
import password_str as pw
import os

import password_str as pwというのは、別に作ったプログラム(import password_str)をimportしています。

import password_str(前回のGithubの説明で作ったものです。)は、同じフォルダに置いてください。

このように、自分でつくった関数、パッケージ、モジュールを使うことができます。

 

9行目から19行目

class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.grid()
        self.create_widgets()
        self.master.title(u"パスワード一覧")
        self.master.geometry("512x512")
        self.id_list = []
        self.pass_list = []
        self.save_list = []
        self.path = os.path.join(os.path.dirname(__file__),'file_data.dat')

初期設定するものを書きます。

self.id_list = []はID名一覧のリストです。

self.pass_list= []はパスワード一覧のリストです。

self.save_list = []はファイル保存用のリストです。

ファイル名を変える場合は、

self.path = os.path.join(os.path.dirname(__file__),'file_data.dat')

を変えてください。

 

21行目から68行目

    def create_widgets(self):
        #リストボックス
        self.ListBox1 = tk.Listbox(self,height=16,width=32)
        self.ListBox1.grid(row=0,column=0,padx=5,pady=5,sticky=tk.N)
        self.ListBox1.bind("<Delete>",self.Delete_press)
        self.ListBox1.bind("<Shift-Delete>",self.Ins_press)
        self.ListBox1.bind("<Double-1>",self.Show_press)
        #スクロールバー
        self.scrollbar1 = tk.Scrollbar(self,orient=tk.VERTICAL,command=self.ListBox1.yview)
        self.ListBox1['yscrollcommand'] = self.scrollbar1.set
        self.scrollbar1.grid(row=0,column=1,sticky=tk.W+tk.N+tk.S)
        #入力ボックスフレーム
        self.in_f = tk.Frame(self.master)
        #入力ボックス1
        self.Label2 = tk.Label(self.in_f,text=u'Name')
        self.Label2.grid(row=0)
        self.TextBox1 = tk.Entry(self.in_f,width=32)
        self.TextBox1.grid(row=1)
        #入力ボックス2
        self.Label3 = tk.Label(self.in_f,text=u'ID')
        self.Label3.grid(row=2)
        self.TextBox2 = tk.Entry(self.in_f,width=32)
        self.TextBox2.grid(row=3)
        #入力ボックス3
        self.Label4 = tk.Label(self.in_f,text=u'Password')
        self.Label4.grid(row=4)
        self.TextBox3 = tk.Entry(self.in_f,width=16)
        self.TextBox3.grid(row=5)
        #入力ボタン
        self.Button1 = tk.Button(self.in_f,text=u'入力ボタン',width=20,command=self.button_clickin)
        self.Button1.grid(row=6,pady=20)
        #入力ボックスフレームの表示
        self.in_f.grid(row=0,column=2)
        #クリアボタン
        self.Button4 = tk.Button(text=u'クリアボタン',width=20,command=self.button_clickcr)
        self.Button4.grid(row=1,column=2,pady=5)
        #保存ボタン
        self.Button2 = tk.Button(text=u'保存ボタン',width=20,command=self.button_clicksv)
        self.Button2.grid(row=2,column=0,pady=5)
        #呼び込みボタン
        self.Button3 = tk.Button(text=u'呼込ボタン',width=20,command=self.button_clickld)
        self.Button3.grid(row=2,column=2,pady=5)
        #パスワード作成ボタン
        self.Button5 = tk.Button(text=u'パスワード作成',width=20,command=self.button_clickpw)
        self.Button5.grid(row=3,column=2,pady=5)
        #通知ラベル
        self.Label1 = tk.Label(root,text=u'処理結果を表示します')
        self.Label1.grid(row=4,pady=20,sticky=tk.W+tk.S)

tkinterで画面を作ります。

31行目で

        #入力ボックスフレーム
        self.in_f = tk.Frame(self.master)

フレームをつくり

51行目で

        #入力ボックスフレームの表示
        self.in_f.grid(row=0,column=2)

で表示しています。

見た目をよくするため、入力関係をまとめています。

 

70行目から76行目

    #入力のクリア
    def button_clickcr(self):
        self.TextBox1.delete(0,tk.END)
        self.TextBox2.delete(0,tk.END)
        self.TextBox3.delete(0,tk.END)
        self.TextBox1.focus_set()
        self.Label1["text"] = u"入力クリアしました"

項目のクリア処理を関数にしています。

        self.TextBox1.focus_set()

で 消去後、self.TextBox1にカーソルを持ってきます。

 

78行目から83行目

    #パスワード作成
    def button_clickpw(self):
        self.TextBox3.delete(0,tk.END)
        Val = pw.pass_make()
        self.TextBox3.insert(tk.END,Val)
        self.Label1["text"] = u"パスワードを作成しました"

パスワード作成のボタンを押したときの処理

Val = pw.pass_make()でimport したpassword_str as pwから関数を呼びます。

(パスワードの桁数を10個に変えたいときは、Val = pw.pass_make(10)のようにします。)

 

83行目から95行目

    #データ入力
    def button_clickin(self):
        self.Val = self.TextBox1.get()
        if self.Val == '':
            self.Label1["text"] = u"入力されていません"
            return
        self.ListBox1.insert(tk.END,self.Val)
        self.Val = self.TextBox2.get()
        self.id_list.append(self.Val)
        self.Val = self.TextBox3.get()
        self.pass_list.append(self.Val)
        self.button_clickcr()

        self.Label1["text"] = u"入力しました"

入力したデータをリストに追加します。

 

99行目から107行目

    #ファイル保存
    def button_clicksv(self):
        self.save_list.append(list(self.ListBox1.get(0,tk.END)))
        self.save_list.append(self.id_list)
        self.save_list.append(self.pass_list)
        with open(self.path,'wb') as file_a:
            pickle.dump(self.save_list,file_a)
        self.Label1["text"] = u"保存しました"
        self.save_list = []

ファイルに保存します。

リストデータを一つにまとめて、保存します。

書き込みは、'wb'のバイナリ形式を使います。

pickle.dumpとは、リスト(オブジェクト)をそのまま書き出します。

(一般的な書き込み方'w'では、文字(数字)に変換しないと書き込めません)

 

109行目から121行目

    #ファイルから呼び込み
    def button_clickld(self):
        if os.path.isfile(self.path) == False:
            self.Label1["text"] = u"ファイルがありません"
            return
        with open(self.path,'rb') as file_a:
            self.save_list = pickle.load(file_a)
        for N in self.save_list[0]:
            self.ListBox1.insert(tk.END,N)
        self.id_list = self.save_list[1]
        self.pass_list = self.save_list[2]
        self.Label1["text"] = u"呼び込みました"
        self.save_list = []

ファイルから呼び込みます。

保存とは逆に一つのリストを三つに戻しています。

pickle.loadとは、リスト(オブジェクト)をそのまま呼び込みます。

保存が'wb'なので、'rb'のバイナリ形式で呼び込みリストに入れます。

 

123行目から129行目

    #項目の削除
    def Delete_press(self,event):
        self.Val = self.ListBox1.index(tk.ACTIVE)
        self.ListBox1.delete(self.Val,self.Val)
        del self.id_list[self.Val]
        del self.pass_list[self.Val]
        self.Label1["text"] = u"指定場所を削除しました"

リストボックスでマウスを離したときの(tk.ACTIVE)場所を削除します。

(Delキーを押すとリストボックスから削除されます。)

 

131行目から141行目

    #項目の挿入
    def Ins_press(self,event):
        self.Val = self.ListBox1.index(tk.ACTIVE)
        self.ins_Val = self.TextBox1.get()
        self.ListBox1.insert(self.Val,self.ins_Val)
        self.ins_Val = self.TextBox2.get()
        self.id_list.insert(self.Val,self.ins_Val)
        self.ins_Val = self.TextBox3.get()
        self.pass_list.insert(self.Val,self.ins_Val)
        self.button_clickcr()
        self.Label1["text"] = u"挿入しました"

リストボックスでマウスを離したときの(tk.ACTIVE)場所に挿入します。

(sHift+Delキーを押すとリストボックスに挿入されます。)

 

143行目から153行目

    #項目の表示
    def Show_press(self,event):
        self.Val = self.ListBox1.index(tk.ACTIVE)
        self.N = self.ListBox1.get(self.Val)
        self.button_clickcr()
        self.TextBox1.insert(tk.END,self.N)
        self.TextBox2.insert(tk.END,self.id_list[self.Val])
        self.TextBox3.insert(tk.END,self.pass_list[self.Val])
        self.master.clipboard_clear()
        self.master.clipboard_append(self.pass_list[self.Val])
        self.Label1["text"] = u"表示しました"

リストボックスでマウスを離したときの(tk.ACTIVE)場所の内容をテキストボックスに表示します。

(ダブルクリックするとリストボックスの内容がテキストボックスに表示されます。)

また、パスワードをクリックボードに貼り付けます。

 

155行目から159行目

#本体
if __name__ == '__main__':
    root = tk.Tk()
    app = Application(master=root)
    app.mainloop()

お決まりの形のメインプログラムです。

 

あと、ハッシュ関数を使ってログインさせようとも思いましたが、いちいち面倒くさいので、

ローカル環境でセキュリティがあればまあいいかと?

(複数で使うときは、ハッシュ関数やデータの暗号化を行ってください。)

 

実際にこのパスワード管理プログラムを使うときは、

ローカル環境かつ共有しない(個人で)環境で自己責任にて使ってください。

 

 

 

JUGEMテーマ:プログラミング

| python | 18:06 | comments(0) | trackbacks(0) |

07
--
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
--
>>
<<
--
Profile
New entries
Archives
Categories
Recent comment
カウンター


今日
昨日
レンタルサーバ/プロバイダー




ファッション
カタログ通販ベルーナ(Belluna)

イマージュ - IMAGEアウトレットセール
yahoo・その他


買い物
ビックカメラ.com



Mobile
qrcode
Links
Others
無料ブログ作成サービス JUGEM