Pythonでコマンドラインの実行

Pythonでコマンドラインの実行

あとはコマンドラインをpythonで実行するメソッドが必要

curl -s -X POST "192.168.1.69:50021/audio_query?speaker=1" --get --data-urlencode text@weather.txt > query.json

でJSONファイルを作成

curl -s -H "Content-Type: application/json" -X POST -d @query.json "192.168.1.69:50021/synthesis?speaker=1" > test_audio.wav

で音声ファイルを作成

これを
Pythonで行うようにする

なおcurl の動作をrequest で行えるらしい

pip install requests simpleaudio

でインストール

Chatgpt で

curl -s -X POST "192.168.1.69:50021/audio_query?speaker=1" --get --data-urlencode text@weather.txt > query.json
でJSONファイルを作成

curl -s -H "Content-Type: application/json" -X POST -d @query.json "192.168.1.69:50021/synthesis?speaker=1" > test_audio.wav
で音声ファイルを作成

これらを python で行い
作成した音声ファイルを再生したい

で調べる

帰ってきた答えは

requests ライブラリを使用して、テキストファイルからJSONファイルを作成し、その後音声ファイルを作成します。次に、pydub や simpleaudio のようなライブラリを使用して音声ファイルを再生

とのこと

生成されたコードは

import requests
import json
import simpleaudio as sa

# テキストファイルを読み込む
with open('weather.txt', 'r') as file:
    text = file.read()

# 最初のPOSTリクエストを行い、JSONを取得
response = requests.post(
    "http://192.168.1.69:50021/audio_query?speaker=1",
    data={'text': text}
)
json_data = response.json()

# JSONデータをファイルに保存
with open('query.json', 'w') as json_file:
    json.dump(json_data, json_file)

# 第二のPOSTリクエストを行い、音声データを取得
response = requests.post(
    "http://192.168.1.69:50021/synthesis?speaker=1",
    json=json_data
)

# 取得した音声データをWAVファイルとして保存
with open('test_audio.wav', 'wb') as audio_file:
    audio_file.write(response.content)

# WAVファイルを読み込み、再生する
wave_obj = sa.WaveObject.from_wave_file('test_audio.wav')
play_obj = wave_obj.play()
play_obj.wait_done()  # 再生が終わるまで待機

これを実験で実行

しかしエラーとなる
原因を調べたら

ChatGPT
このエラーメッセージは、simpleaudio モジュールがあなたのシステムのアーキテクチャと互換性がないことを示しています。エラーによると、インストールされたsimpleaudioはx86_64アーキテクチャ用ですが、あなたのシステムはarm64アーキテクチャを必要

とあるため
pygame や pydub などを使う必要がある

pip install requests pygame

の後に

import requests
import json
import pygame

# テキストファイルの内容を読み込む
with open('weather.txt', 'r') as file:
    text = file.read()

# POSTリクエストでJSONデータを取得
response = requests.post(
    "http://192.168.1.69:50021/audio_query?speaker=1",
    data={'text': text}
)
json_data = response.json()

# JSONデータをファイルに保存
with open('query.json', 'w') as json_file:
    json.dump(json_data, json_file)

# JSONファイルを読み込む
with open('query.json', 'r') as json_file:
    json_payload = json.load(json_file)

# POSTリクエストで音声ファイルを取得
response = requests.post(
    "http://192.168.1.69:50021/synthesis?speaker=1",
    json=json_payload
)

# 音声データをファイルに保存
with open('test_audio.wav', 'wb') as audio_file:
    audio_file.write(response.content)

# Pygameの初期化
pygame.init()
pygame.mixer.init()

# WAVファイルを読み込む
sound = pygame.mixer.Sound("test_audio.wav")

# 再生
sound.play()

# 再生が終了するまで待機
while pygame.mixer.get_busy():
    pygame.time.Clock().tick(10)

で実行したが

pygame 2.5.2 (SDL 2.28.3, Python 3.10.6)
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "/Users/snowpool/aw10s/weather/weather_audio.py", line 39, in <module>
    sound = pygame.mixer.Sound("test_audio.wav")
pygame.error: Unrecognized audio format

となる

とりあえず問題を分割
音声の再生ができるかテスト

cp ../test_audio.wav .

あとは

import pygame

# Pygameの初期化
pygame.init()
pygame.mixer.init()

# WAVファイルを読み込む
sound = pygame.mixer.Sound("test_audio.wav")

# 再生
sound.play()

# 再生が終了するまで待機
while pygame.mixer.get_busy():
    pygame.time.Clock().tick(10)

で音声が再生されるのを確認

となると問題は音声ファイルの作成プロセス

import requests
import json

# テキストファイルを読み込む
with open('weather.txt', 'r') as file:
    text = file.read()

# 最初のPOSTリクエストを行い、JSONを取得
response = requests.post(
    "http://192.168.1.69:50021/audio_query?speaker=1",
    data={'text': text}
)
json_data = response.json()

# JSONデータをファイルに保存
with open('query.json', 'w') as json_file:
    json.dump(json_data, json_file)

# 第二のPOSTリクエストを行い、音声データを取得
response = requests.post(
    "http://192.168.1.69:50021/synthesis?speaker=1",
    json=json_data
)

# 取得した音声データをWAVファイルとして保存
with open('test_audio.wav', 'wb') as audio_file:
    audio_file.write(response.content)

で作成したファイルは音声が再生されない

作成に必要なJSONファイルを見てみると
失敗の方は

{"detail": [{"loc": ["query", "text"], "msg": "field required", "type": "value_error.missing"}]}

成功は

{"accent_phrases":[{"moras":[{"text":"キョ","consonant":"ky","consonant_length":0.12866447865962982,"vowel":"o","vowel_length":0.0973580852150917,"pitch":5.962612628936768},{"text":"オ","consonant":null,"consonant_length":null,"vowel":"o","vowel_length":0.09024209529161453,"pitch":6.068655967712402},{"text":"ノ","consonant":"n","consonant_length":0.05692561715841293,"vowel":"o","vowel_length":0.11087840050458908,"pitch":5.8726630210876465}],"accent":1,"pause_mora":null,"is_interrogative":false},{"moras":[{"text":"テ","consonant":"t","consonant_length":0.0718907043337822,"vowel":"e","vowel_length":0.14058615267276764,"pitch":5.855612277984619},{"text":"ン","consonant":null,"consonant_length":null,"vowel":"N","vowel_length":0.08981689810752869,"pitch":5.842429161071777},{"text":"キ","consonant":"k","consonant_length":0.07256065309047699,"vowel":"i","vowel_length":0.07487940043210983,"pitch":5.817480087280273},{"text":"ワ","consonant":"w","consonant_length":0.057370081543922424,"vowel":"a","vowel_length":0.12027011066675186,"pitch":5.624467849731445}],"accent":1,"pause_mora":null,"is_interrogative":false},{"moras":[{"text":"ク","consonant":"k","consonant_length":0.07742901891469955,"vowel":"u","vowel_length":0.0734512135386467,"pitch":5.836529731750488},{"text":"モ","consonant":"m","consonant_length":0.060555391013622284,"vowel":"o","vowel_length":0.18545563519001007,"pitch":5.841731071472168}],"accent":1,"pause_mora":{"text":"、","consonant":null,"consonant_length":null,"vowel":"pau","vowel_length":0.33395129442214966,"pitch":0.0},"is_interrogative":false},{"moras":[{"text":"ヨ","consonant":"y","consonant_length":0.10122014582157135,"vowel":"o","vowel_length":0.08855406194925308,"pitch":5.50715970993042},{"text":"ソ","consonant":"s","consonant_length":0.09714090079069138,"vowel":"o","vowel_length":0.09897967427968979,"pitch":5.924524784088135},{"text":"オ","consonant":null,"consonant_length":null,"vowel":"o","vowel_length":0.10465160012245178,"pitch":6.014603614807129},{"text":"サ","consonant":"s","consonant_length":0.09610642492771149,"vowel":"a","vowel_length":0.11944571882486343,"pitch":6.102450370788574},{"text":"イ","consonant":null,"consonant_length":null,"vowel":"i","vowel_length":0.08921179920434952,"pitch":6.081024169921875},{"text":"コ","consonant":"k","consonant_length":0.07877751439809799,"vowel":"o","vowel_length":0.08582849055528641,"pitch":6.140597343444824},{"text":"オ","consonant":null,"consonant_length":null,"vowel":"o","vowel_length":0.11994349211454391,"pitch":6.1246795654296875},{"text":"キ","consonant":"k","consonant_length":0.08878674358129501,"vowel":"i","vowel_length":0.09810564666986465,"pitch":6.173953533172607},{"text":"オ","consonant":null,"consonant_length":null,"vowel":"o","vowel_length":0.16754235327243805,"pitch":6.181836128234863},{"text":"ン","consonant":null,"consonant_length":null,"vowel":"N","vowel_length":0.06746162474155426,"pitch":6.051656723022461},{"text":"ワ","consonant":"w","consonant_length":0.04867963492870331,"vowel":"a","vowel_length":0.1127525344491005,"pitch":5.779387950897217}],"accent":8,"pause_mora":null,"is_interrogative":false},{"moras":[{"text":"ジュ","consonant":"j","consonant_length":0.11186956614255905,"vowel":"u","vowel_length":0.10070556402206421,"pitch":5.609426498413086},{"text":"ウ","consonant":null,"consonant_length":null,"vowel":"u","vowel_length":0.08927937597036362,"pitch":5.8536553382873535}],"accent":2,"pause_mora":null,"is_interrogative":false},{"moras":[{"text":"ゴ","consonant":"g","consonant_length":0.06749280542135239,"vowel":"o","vowel_length":0.09443604201078415,"pitch":6.002788543701172},{"text":"オ","consonant":null,"consonant_length":null,"vowel":"o","vowel_length":0.12283030897378922,"pitch":6.167281150817871},{"text":"テ","consonant":"t","consonant_length":0.07367654889822006,"vowel":"e","vowel_length":0.14059318602085114,"pitch":6.100039958953857},{"text":"ン","consonant":null,"consonant_length":null,"vowel":"N","vowel_length":0.08243037015199661,"pitch":5.868035316467285}],"accent":1,"pause_mora":null,"is_interrogative":false},{"moras":[{"text":"サ","consonant":"s","consonant_length":0.08632750064134598,"vowel":"a","vowel_length":0.1564868539571762,"pitch":5.76937198638916},{"text":"ン","consonant":null,"consonant_length":null,"vowel":"N","vowel_length":0.0757487341761589,"pitch":5.765336036682129}],"accent":2,"pause_mora":null,"is_interrogative":false},{"moras":[{"text":"ゴ","consonant":"g","consonant_length":0.05643042176961899,"vowel":"o","vowel_length":0.09696970134973526,"pitch":5.819827079772949},{"text":"オ","consonant":null,"consonant_length":null,"vowel":"o","vowel_length":0.10339736193418503,"pitch":5.959120273590088},{"text":"ド","consonant":"d","consonant_length":0.06090632826089859,"vowel":"o","vowel_length":0.17854683101177216,"pitch":5.801456451416016}],"accent":2,"pause_mora":{"text":"、","consonant":null,"consonant_length":null,"vowel":"pau","vowel_length":0.3034582734107971,"pitch":0.0},"is_interrogative":false},{"moras":[{"text":"ヨ","consonant":"y","consonant_length":0.09282273054122925,"vowel":"o","vowel_length":0.08764959871768951,"pitch":5.5444231033325195},{"text":"ソ","consonant":"s","consonant_length":0.09865055978298187,"vowel":"o","vowel_length":0.09965776652097702,"pitch":5.934866905212402},{"text":"オ","consonant":null,"consonant_length":null,"vowel":"o","vowel_length":0.10340947657823563,"pitch":6.015321731567383},{"text":"サ","consonant":"s","consonant_length":0.09463881701231003,"vowel":"a","vowel_length":0.11840283870697021,"pitch":6.101940155029297},{"text":"イ","consonant":null,"consonant_length":null,"vowel":"i","vowel_length":0.08852870017290115,"pitch":6.076019287109375},{"text":"テ","consonant":"t","consonant_length":0.0689489021897316,"vowel":"e","vowel_length":0.09846750646829605,"pitch":6.127346038818359},{"text":"エ","consonant":null,"consonant_length":null,"vowel":"e","vowel_length":0.1237698420882225,"pitch":6.114901542663574},{"text":"キ","consonant":"k","consonant_length":0.08733474463224411,"vowel":"i","vowel_length":0.0968116894364357,"pitch":6.151494026184082},{"text":"オ","consonant":null,"consonant_length":null,"vowel":"o","vowel_length":0.1778039187192917,"pitch":6.152987480163574},{"text":"ン","consonant":null,"consonant_length":null,"vowel":"N","vowel_length":0.064981609582901,"pitch":6.005949974060059},{"text":"ワ","consonant":"w","consonant_length":0.04751142859458923,"vowel":"a","vowel_length":0.09467842429876328,"pitch":5.725627899169922}],"accent":8,"pause_mora":null,"is_interrogative":false},{"moras":[{"text":"ロ","consonant":"r","consonant_length":0.0632673129439354,"vowel":"o","vowel_length":0.10540910810232162,"pitch":5.67587947845459},{"text":"ク","consonant":"k","consonant_length":0.06531907618045807,"vowel":"U","vowel_length":0.05817136913537979,"pitch":0.0},{"text":"テ","consonant":"t","consonant_length":0.07730791717767715,"vowel":"e","vowel_length":0.16715875267982483,"pitch":6.10499382019043},{"text":"ン","consonant":null,"consonant_length":null,"vowel":"N","vowel_length":0.06785128265619278,"pitch":5.860898494720459}],"accent":1,"pause_mora":null,"is_interrogative":false},{"moras":[{"text":"ロ","consonant":"r","consonant_length":0.03526639938354492,"vowel":"o","vowel_length":0.11113513261079788,"pitch":5.707563877105713},{"text":"ク","consonant":"k","consonant_length":0.07907760888338089,"vowel":"u","vowel_length":0.07053706794977188,"pitch":5.830077648162842}],"accent":2,"pause_mora":null,"is_interrogative":false},{"moras":[{"text":"ゴ","consonant":"g","consonant_length":0.072600357234478,"vowel":"o","vowel_length":0.09719936549663544,"pitch":5.857402324676514},{"text":"オ","consonant":null,"consonant_length":null,"vowel":"o","vowel_length":0.09454251080751419,"pitch":6.060022354125977},{"text":"ド","consonant":"d","consonant_length":0.05659743398427963,"vowel":"o","vowel_length":0.08684452623128891,"pitch":6.083237171173096},{"text":"デ","consonant":"d","consonant_length":0.05277804285287857,"vowel":"e","vowel_length":0.14346836507320404,"pitch":5.951061248779297},{"text":"ス","consonant":"s","consonant_length":0.07407647371292114,"vowel":"U","vowel_length":0.12432015687227249,"pitch":0.0}],"accent":2,"pause_mora":null,"is_interrogative":false}],"speedScale":1.0,"pitchScale":0.0,"intonationScale":1.0,"volumeScale":1.0,"prePhonemeLength":0.1,"postPhonemeLength":0.1,"outputSamplingRate":24000,"outputStereo":false,"kana":"キョ'オノ/テ'ンキワ/ク'モ、ヨソオサイコオキ'オンワ/ジュウ'/ゴ'オテン/サン'/ゴオ'ド、ヨソオサイテエキ'オンワ/ロ'_クテン/ロク'/ゴオ'ドデ_ス"}

となる

つまりJSON作成が失敗している

Request による生成を断念
代わりに subprocess によるLinux コマンドを実行する方法に買える

import subprocess

# curl コマンドを定義
command = [
    "curl", "-s", "-X", "POST",
    "192.168.1.69:50021/audio_query?speaker=1",
    "--get", "--data-urlencode", "text@weather.txt"
]

# コマンドを実行し、出力を query.json にリダイレクト
with open('query.json', 'w') as file:
    subprocess.run(command, stdout=file)

でサブプロセスを使う方法にすると
JSONファイルの作成が成功

これを

curl -s -H "Content-Type: application/json" -X POST -d @query.json "192.168.1.69:50021/synthesis?speaker=1" > test_audio.wav

とすると音声ファイルができているのを確認

次に一緒に音声ファイル作成までをpython でやるようにする

import subprocess

# 最初のcurlコマンド(JSONファイルの作成)
command_json = [
    "curl", "-s", "-X", "POST",
    "192.168.1.69:50021/audio_query?speaker=1",
    "--get", "--data-urlencode", "text@weather.txt"
]

# 第二のcurlコマンド(音声ファイルの作成)
command_audio = [
    "curl", "-s", "-H", "Content-Type: application/json", "-X", "POST",
    "-d", "@query.json", "192.168.1.69:50021/synthesis?speaker=1"
]

# 最初のコマンドを実行してJSONファイルを作成
with open('query.json', 'w') as file:
    subprocess.run(command_json, stdout=file)

# 第二のコマンドを実行して音声ファイルを作成
with open('test_audio.wav', 'wb') as file:
    subprocess.run(command_audio, stdout=file)

これで音声ファイルができているのを確認できたので
次に
これをpygame. で再生する

import subprocess
import pygame
import time

# JSONファイルを作成するためのcurlコマンド
command_json = [
    "curl", "-s", "-X", "POST",
    "192.168.1.69:50021/audio_query?speaker=1",
    "--get", "--data-urlencode", "text@weather.txt"
]

# 音声ファイルを作成するためのcurlコマンド
command_audio = [
    "curl", "-s", "-H", "Content-Type: application/json", "-X", "POST",
    "-d", "@query.json", "192.168.1.69:50021/synthesis?speaker=1"
]

# 最初のコマンドを実行してJSONファイルを作成
with open('query.json', 'w') as file:
    subprocess.run(command_json, stdout=file)

# 第二のコマンドを実行して音声ファイルを作成
with open('test_audio.wav', 'wb') as file:
    subprocess.run(command_audio, stdout=file)

# Pygameの初期化
pygame.init()
pygame.mixer.init()

# WAVファイルを読み込む
sound = pygame.mixer.Sound("test_audio.wav")

# 再生
sound.play()

# 再生が終了するまで待機
while pygame.mixer.get_busy():
    time.sleep(0.1)

これでようやくcurl でファイルを作成し
Pygame で音声再生ができるようになった

次はテキストファイルではなく
Weather map api へアクセスし
その結果をテキストファイルへ保存
それを変換する
もしくはそのまま処理するようにする