Logo
リアルタイム音声認識

Python SDK

1 概要

音声対話サービスのためのPython SDKです。

対応しているサービス 一発話認識、リアルタイム音声認識。

取扱説明書をよくお読みください

1.1 SDKファイルの説明

ファイル/ディレクトリ説明
speech_recSDK関連ファイル
demoコード例
 ├─ transcriber_demo.pyリアルタイム音声認識サンプルコード
 ├─ recognizer_demo.py一発話認識例コード
 ├─ demo.wav中国語(北京語)サンプル音声(WAV形式)
 ├─ demo.mp3中国語(北京語)サンプル音声(MP3形式)
setup.pyインストールファイル
README-JA.md日本語説明文書
README-EN.md英語説明文書

注意:SDKで提供されるテスト音声の認識結果は一定です。デフォルトで使用される音声はMP3形式です。入力された音声がWAVやその他の形式の場合、MP3形式に変換されます。

2 動作環境

Python3.4以降、ffmpeg。

Pythonの実行環境を別に作成することをお勧めします。そうしないとバージョンの衝突が発生する可能性があります。

3 設置方法

1.Pythonパッケージ管理ツールsetuptoolsがインストールされていることを確認する。インストールされていない場合は、インストールしてください:

$ pip install setuptools

2.SDKを解凍し、フォルダ(setup.pyファイルがあるフォルダ)に移動し、SDKディレクトリで以下のコマンドを実行します:

Install

$ python setup.py install Note: - The above pip and python commands correspond to Python3.

  • If the following information is displayed, the installation is successful: Finished processing dependencies for speech-python-rec-sdk==1.0.0.8
  • After installation, the build, dist, and speech_python_rec_sdk.egg-info files are generated.

3.demoのファイルの具体的なパラメーターを修正する:

recognizer_demo.py and transcriber_demo.py are execution files for one-sentence recognition and real-time speech recognition, respectively.

//Enter the appID that you get when you purchase a service in the platform app_id = '#####'

//Enter appSecret, which you get when you purchase a service in the platform app_secret = '#####'

//Enter the path of the voice file to be identified. Change it to the path of the customized audio file audio_path = '####'

//Input language, format see platform documentation center-Speech recognition-Development Guide lang_type = 'ja-JP'

4.recognizer_demo.pyまたはtranscriber_demo.pyを実行して音声を認識します。トークンの認識に失敗したり、有効期限が切れたりした場合は、ローカルのSpeechRecognizer_token.txtファイルまたはSpeechTranscriber_token.txtファイルを削除して再度お試しください。それでも期限切れの場合は、技術スタッフまでご連絡ください。

To run the command in the demo directory, set parameters such as app_id corresponding to python files in the demo.

$ python recognizer_demo.py $ python transcriber_demo.py #After the successful run, the SpeechRecognizer_token.txt or SpeechTranscriber_token.txt files are generated in the path where the demo is running.

注意: 「timestamp timeout 」または 「timestamp is greater than current time 」と表示された場合、ローカル時間とサーバー時間が一致していません。エラーメッセージの時差に応じて、

speech-python-recファイルの_token.pyファイルを修正し、timestamp = int(t)の行コードを適切に修正します。

timestamp = int(t)+1または2,3,4など、またはtimestamp = int(t)-1または2,3,4など。

  • After _token.py is modified, the modification takes effect only after it is created again. The specific steps are as follows:

Delete build, dist, and speech_python_rec_sdk.egg-info files created and generated in the SDK directory.

To uninstall and reinstall the SDK, run $pip uninstall speech-python-rec-sdk and repeat steps 2,3,4.

4 パラメータの説明

4.1 リアルタイム音声認識デモ

speech_rec/demo/transcriber_demo.py これはリアルタイムの音声認識デモで、直接実行することができる。

4.1.1 キー・インターフェースの説明

リアルタイム音声認識SDKは主にTranscriberクラスを使用して完成され、Tokenクラスを使用してコード呼び出しのステップを完了することが許可されています:

  1. SpeechClientクラスの get_token() メソッドを呼び出してトークンを取得する。
  2. SpeechTranscriber のインスタンスを作成する。
  3. Callback インスタンスを作成する。
  4. パラメータを設定するには、SpeechTranscriber インスタンスの set_token() メソッドを呼び出します。
  5. SpeechTranscriber インスタンスの start() メソッドを呼び出して、サーバーに接続する。
  6. I音声を送信するために SpeechTranscriber インスタンスの send() メソッドを呼び出します。
  7. SpeechTranscriber インスタンスの stop() メソッドを呼び出して、送信を停止する。
  8. SpeechTranscriberインスタンスの close() メソッドを呼び出して、サーバーとの接続を切断する。

4.1.2 パラメータの説明

パラメータタイプ必須説明デフォルト値
lang_typeStringはい言語オプション必須
formatStringいいえ音声エンコード形式pcm
sample_rateIntegerいいえ音声サンプルレート
sample_rate=「8000」の場合
fieldパラメータ・フィールドが必須で、かつfield=「call-center」
16000
enable_intermediate_resultBooleanいいえ中間認識結果を返すかどうかtrue
enable_punctuation_predictionBooleanいいえ後処理で句読点を追加するかどうかtrue
enable_inverse_text_normalizationBooleanいいえ後処理でITNを実行するかどうかtrue
max_sentence_silenceIntegerいいえ音声センテンスの静寂検出しきい値、静寂時間がこのしきい値を超えるとセンテンスが切り替えられます。有効なパラメータ範囲は200~1200で、単位はミリ秒ですsample_rate=16000:800
sample_rate=8000:250
enable_wordsBooleanいいえ単語情報を返すかどうかfalse
enable_intermediate_wordsBooleanいいえ中間結果の単語情報を返すかどうかfalse
enable_modal_particle_filterBooleanいいえ語気詞フィルタを有効にするかどうかtrue
hotwords_listList<String>いいえ一度限り有効な単語リスト、本接続中のみ有効です
hotwords_id と同時に存在する場合は、hotwords_list が優先されます。一度に最大 100 個まで提供可能です
無し
hotwords_idStringいいえ単語ID無し
hotwords_weightFloatいいえ単語ウェイト、値の範囲[0.1, 1.0]0.4
correction_words_idStringいいえ強制置換単語庫ID
複数の強制置換単語庫IDを使用することができ、各IDは縦線|で区切られます;all は全ての強制置換単語庫IDを使用することを意味します
無し
forbidden_words_idStringいいえNG単語ID
複数のNG単語IDを使用することができ、各IDは縦線|で区切られます;all は全てのNG単語IDを使用することを意味します
無し
fieldStringいいえ分野
一般:general (サポートサンプルレート16000Hz)
コールセンター:call-center (サポートサンプルレート8000Hz)
無し
audio_urlStringいいえ戻り音声のフォーマット(プラットフォームでは30日間のみ保存)
mp3:mp3形式の音声リンクを返す
pcm:pcm形式の音声リンクを返す
wav:wav形式の音声リンクを返す
無し
connect_timeoutIntegerいいえ接続タイムアウト(秒)、範囲:5-6010
gainIntegerいいえ振幅増幅係数を表し、範囲[1, 20]
1は拡大しないことを示し、2は元の振幅の2倍(拡大1倍)を示し、以下同様
sample_rate=16000:1
sample_rate=8000:2
user_idStringいいえユーザーが定義した情報で、応答メッセージにそのまま返され、最大36文字までです無し
enable_lang_labelBooleanいいえ言語を切り替える際に、認識結果に言語ラベルを返す:現在は日英混合、中英混合言語のみ対応しています。注意:この機能を有効にすると、言語切り替え時に応答の遅延が発生しますfalse
paragraph_conditionIntegerいいえ同じ speakerid 内で設定された文字数に達したら、次の文で新しい段落番号を返す:範囲[100, 2000]、範囲外の値はこの機能を無効化します0
enable_save_logBooleanいいえ音声データと認識結果のログを提供して、弊社が製品とサービスの質を向上させるために使用することは可能ですかtrue

4.1.3 リアルタイム音声認識サンプルコード

完全なコードはSDKのspeech_python_rec/demo/transcriber_demo.pyファイルを参照してください。

# -*- coding: utf-8 -*-
import json
import os.path
import time
import threading
import traceback

import speech_rec
from speech_rec.callbacks import SpeechTranscriberCallback
from speech_rec.parameters import DefaultParameters, Parameters

token = None
expire_time = 7  # Expiration time

info_list = [[], [], False]


class MyCallback(SpeechTranscriberCallback):
    """
    The parameters of the constructor are not required. You can add them as needed
    The name parameter in the example can be used as the audio file name to be recognized for distinguishing in multithreading
    """

    def __init__(self, name='default'):
        self._name = name

    def started(self, message):
        self.print_message(message)

    def result_changed(self, message):
        self.print_message(message)

    def sentence_begin(self, message):
        self.print_message(message)

    def sentence_end(self, message):
        global info_list
        channel = message['header']['user_id']
        begin_time = message['payload']['begin_time']
        end_time = message['payload']['time']
        result = message['payload']['result']
        if channel == "left" or channel == "right":
            if channel == "left":
                if result:
                    info_list[0].append([channel, begin_time, end_time, result])
            elif channel == "right":
                if result:
                    info_list[1].append([channel, begin_time, end_time, result])
            self.print_info()
        else:
            print(message)

    def completed(self, message):
        try:
            print(message)
        except Exception as ee:
            print(ee)
            traceback.print_exc()
        global info_list
        info_list[2] = True

    def print_info(self, ):
        left_list = info_list[0]
        right_list = info_list[1]
        if_end = info_list[2]

        def format_string(data_list, list_name):
            channel, begin_time, end_time, result = data_list[0]
            if list_name == "left_list":
                info_list[0].pop(0)
            else:
                info_list[1].pop(0)

            return f"channel:{channel}\tbegin_time:{begin_time}\tend_time:{end_time}\tresult:{result}"

        if left_list and right_list:
            while True:
                if not left_list and not right_list:
                    break
                if left_list and right_list:
                    left_begin_time = left_list[0][1]
                    left_end_time = left_list[0][2]
                    right_begin_time = right_list[0][1]
                    right_end_time = right_list[0][2]
                    if left_begin_time == right_begin_time and left_end_time > right_end_time:
                        print(format_string(right_list, "right_list"))
                    elif left_begin_time == right_begin_time and left_end_time <= right_end_time:
                        print(format_string(left_list, "left_list"))
                    elif left_begin_time < right_begin_time:
                        print(format_string(left_list, "left_list"))
                    elif left_begin_time >= right_begin_time:
                        print(format_string(right_list, "right_list"))
                if left_list and not right_list:
                    if left_end_time > right_end_time:
                        break
                    else:
                        print(format_string(left_list, "left_list"))
                if not left_list and right_list:
                    if right_end_time > left_end_time:
                        print(format_string(right_list, "right_list"))
                    else:
                        break
        elif if_end:
            while left_list:
                print(format_string(left_list, "left_list"))
            while right_list:
                print(format_string(right_list, "right_list"))

    def print_message(self, message):
        channel = message['header']['user_id']
        if channel == "left" or channel == "right":
            pass
        else:
            print(message)

    def task_failed(self, message):
        print(message)

    def warning_info(self, message):
        print(message)

    def channel_closed(self):
        print('MyCallback.OnTranslationChannelClosed')


def solution(client, app_id, app_secret, audio_path, lang_type, kwargs):
    """
    Transcribe speech,single thread
    :param client: SpeechClient
    :param app_id: Your app_id
    :param app_secret: Your app_secret
    :param audio_path: Audio path
    :param lang_type: Language type
    """
    each_audio_format = kwargs.get("audio_format", DefaultParameters.MP3)
    field_ = kwargs.get("field", DefaultParameters.FIELD)
    user_id = kwargs.get("user_id", "default")
    print("ccc",kwargs)
    assert os.path.exists(audio_path), "Audio file path error, please check your audio path."
    if judging_expire_time(app_id, app_secret, expire_time):
        callback = MyCallback(audio_path)
        transcriber = client.create_transcriber(callback)
        transcriber.set_app_id(app_id)
        transcriber.set_token(token)
        # fixme You can customize the configuration according to the official website documentation
        payload = {
            "lang_type": lang_type,
            "format": each_audio_format,
            "field": field_,
            "sample_rate": sample_rate,
            "user_id": user_id
        }
        transcriber._payload.update(**payload)
        try:
            ret = transcriber.start()
            if ret < 0:
                return ret
            with open(audio_path, 'rb') as f:
                audio = f.read(7680)
                cnt = 0
                while audio:
                    ret = transcriber.send(audio)
                    # fixme: If you need to mandatory clause or set speaker id by yourself, please use the codes below

                    # Default, customizable and changeable
                    # if cnt % 768000 == 0:
                    #     # Mandatory clause setting
                    #     transcriber.set_mandatory_clause(True)
                    #     transcriber._header = transcriber.get_mandatory_clause()
                    #     transcriber.send(json.dumps({Parameters.HEADER: transcriber._header}), False)
                    #     # Set speaker ID
                    #     transcriber.set_speaker_id(speaker_id)
                    #     speaker_id_info = transcriber.get_speaker_id()
                    #     transcriber.send(json.dumps(speaker_id_info), False)
                    #     print("Mandatory and Set speaker:",transcriber._payload)

                    if ret < 0:
                        break
                    cnt += 7680
                    time.sleep(0.24)
                    audio = f.read(7680)
            transcriber.stop()
        except Exception as e:
            print(e)
        finally:
            transcriber.close()
    else:
        print("token expired")


def judging_expire_time(app_id, app_secret, extime):
    global token
    token_file = "SpeechTranscriber_token.txt"
    new_time = time.time()
    if not os.path.exists(token_file):
        client.get_token(app_id, app_secret, token_file)

    with open(token_file, "r", encoding="utf-8") as fr:
        token_info = eval(fr.read())
    old_time = token_info['time']
    token = token_info['token']
    flag = True
    if new_time - old_time > 60 * 60 * 24 * (extime - 1):
        flag, _ = client.get_token(app_id, app_secret, token_file)
        if flag:
            flag = True
            pass
        else:
            for i in range(7):
                flag, _ = client.get_token(app_id, app_secret, token_file)
                if flag is not None:
                    flag = True
                    break
    return flag


def channels_split_solution(audio_path, right_path, left_path, **kwargs):
    client = kwargs.get('client')
    appid = kwargs.get('app_id')
    appsecret = kwargs.get('app_secret')
    langtype = kwargs.get('lang_type')
    remove_audio = kwargs.get('rm_audio', True)
    client.auto_split_audio(audio_path, right_path, left_path)
    thread_list = []
    right_kwargs = kwargs.copy()
    right_kwargs["user_id"] = "right"
    thread_r = threading.Thread(target=solution, args=(client, appid, appsecret, right_path, langtype, right_kwargs))
    thread_list.append(thread_r)
    left_kwargs = kwargs.copy()
    left_kwargs["user_id"] = "left"
    thread_l = threading.Thread(target=solution, args=(client, appid, appsecret, left_path, langtype, left_kwargs))
    thread_list.append(thread_l)
    for thread in thread_list:
        thread.start()
    for thread in thread_list:
        thread.join()
    if remove_audio:
        try:
            os.remove(right_path)
            os.remove(left_path)
        except Exception as ee:
            print(ee)
            traceback.print_exc()


if __name__ == "__main__":
    client = speech_rec.SpeechClient()
    # Set the level of output log information:DEBUG、INFO、WARNING、ERROR
    client.set_log_level('INFO')
    # Type your app_id and app_secret
    app_id = ""  # your app id
    app_secret = ""  # your app secret
    audio_path = ""  # audio path
    lang_type = ""  # lang type
    field = ""  # field
    sample_rate = 16000  # sample rate [int] 16000 or 8000
    audio_format = ""  # audio format
    assert app_id and app_secret and audio_path and lang_type and field and sample_rate and audio_format, "Please check args"
    channel = client.get_audio_info(audio_path)['channel']
    # fixme This is just a simple example, please modify it according to your needs.
    if channel == 1:
        kwargs = {
            "field": field,
            "sample_rate": sample_rate,
            "audio_format": audio_format,
            "user_id": "",
        }
        solution(client, app_id, app_secret, audio_path, lang_type, kwargs)
    elif channel == 2:
        # Dual channel 8K audio solution
        channels_split_solution(audio_path=audio_path,
                                left_path=f"left.{audio_format}",
                                right_path=f"right.{audio_format}",
                                client=client,
                                app_id=app_id,
                                app_secret=app_secret,
                                lang_type=lang_type,
                                field=field,
                                sample_rate=sample_rate,
                                audio_format=audio_format,
                                )

5 SDKダウンロード

Python SDK