ロシアの会社Stelの無料音声認識

音声付きの音声ファイルをテキストに変換する必要が生じた場合、GoogleとYandexの決定が最初に思い浮かびます。 しかし、Yandexのほかに、別の国内企業があります-「Stel」( http://speech.stel.ru/ )、そのAPIは1日あたり「9000以上」および「非常に多くの」要求さえサポートし、Stelは試用キーを配布します無料で。



画像







APIを扱うのはそれほど難しくありませんが、この記事を書いている時点では、StelaのWebサイトのマニュアルは古く、機能していません。そのため、PythonとJavaの例を含むマニュアルをここに示します。 Javaの例は、サウンドファイルがファイルの形式ではなく、バイトの配列である場合に特に関連します。 Stelは、サンプリング周波数が8 kHz、サンプルサイズが16ビット、モノ(1チャンネル)のwavファイルでのみ動作することに注意してください。



ポイントに近い:Stel Webサイト( http://speech.stel.ru/api_description )で、何とどのように(現時点では少し時代遅れですが)詳細に説明されているため、すぐに(今も)動作する例を示しますPythonの場合:



coding: utf-8 import httplib, json, base64 HOST = 'api.stel.ru:7071' APIKEY = '***' # Place your API key here MODEL = 'rus_gsm_ext' WAV = base64.b64encode(open('test.wav', 'rb').read()) # demo audio file (WAV, 8000 HZ, 16-bit, mono) con = httplib.HTTPConnection(HOST) #Speech recognition data = json.dumps({'apikey' : APIKEY, 'model': MODEL , 'wav' : WAV}) headers = {'Content-Type' : 'application/json', 'Accept': 'application/json', 'Content-Length' : '{0}'.format(len(data))} con.request('POST', '/kwfind', data, headers) resp = con.getresponse() if resp.status == 200: print json.loads(resp.read()) # UTF-8 string with recognized text else: print resp.reason
      
      







ご覧のとおり、ここではtest.wavがスクリプトの作業ディレクトリから認識のために送信されます。 同様のJavaコードと、バイト配列で機能するコードを以下に示します。 最初に、バイト配列(マークアップなし)とファイルを指定された形式のwavファイルに対応するバイト配列に変換するクラス(8000ヘルツ、2バイト、1チャネルが必要です):



 package ru.habrahabr.stel.example; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.UnsupportedAudioFileException; public class WaveFile { private int INT_SIZE = 4; public final int NOT_SPECIFIED = -1; private int sampleSize = NOT_SPECIFIED; private long framesCount = NOT_SPECIFIED; private byte[] data = null; private AudioInputStream ais = null; private AudioFormat af = null; WaveFile(File file) throws UnsupportedAudioFileException, IOException { if(!file.exists()) { throw new FileNotFoundException(file.getAbsolutePath()); } ais = AudioSystem.getAudioInputStream(file); af = ais.getFormat(); framesCount = ais.getFrameLength(); sampleSize = af.getSampleSizeInBits()/8; long dataLength = framesCount*af.getSampleSizeInBits()*af.getChannels()/8; data = new byte[(int) dataLength]; ais.read(data); } WaveFile(int sampleSize, float sampleRate, int channels, int[] samples) throws Exception { if(sampleSize < INT_SIZE) { throw new Exception("sample size < int size"); } this.sampleSize = sampleSize; this.af = new AudioFormat(sampleRate, sampleSize*8, channels, true, false); this.data = new byte[samples.length*sampleSize]; for(int i=0; i < samples.length; i++) { setSampleInt(i, samples[i]); } framesCount = data.length / (sampleSize*af.getChannels()); ais = new AudioInputStream(new ByteArrayInputStream(data), af, framesCount); } WaveFile(int sampleSize, float sampleRate, int channels, byte[] wave) throws Exception { this.sampleSize = sampleSize; this.af = new AudioFormat(sampleRate, sampleSize*8, channels, true, false); this.data = Arrays.copyOf(wave, wave.length); framesCount = data.length / (sampleSize*af.getChannels()); ais = new AudioInputStream(new ByteArrayInputStream(data), af, framesCount); } public AudioFormat getAudioFormat() { return af; } public byte[] getData() { return Arrays.copyOf(data, data.length); } public byte[] getWave() throws Exception { ByteArrayOutputStream bts = new ByteArrayOutputStream(); AudioSystem.write(new AudioInputStream(new ByteArrayInputStream(data), af, framesCount), AudioFileFormat.Type.WAVE, bts); return bts.toByteArray(); } public int getSampleSize() { return sampleSize; } public double getDurationTime() { return getFramesCount() / getAudioFormat().getFrameRate(); } public long getFramesCount() { return framesCount; } public void saveFile(File file) throws IOException { AudioSystem.write( new AudioInputStream(new ByteArrayInputStream(data), af, framesCount), AudioFileFormat.Type.WAVE, file); } public int getSampleInt(int sampleNumber) { if(sampleNumber < 0 || sampleNumber >= data.length/sampleSize) { throw new IllegalArgumentException( "sample number is can't be < 0 or >= data.length/" + sampleSize); } byte[] sampleBytes = new byte[sampleSize]; for(int i=0; i < sampleSize; i++) { sampleBytes[i] = data[sampleNumber * sampleSize + i]; } int sample = ByteBuffer.wrap(sampleBytes) .order(ByteOrder.LITTLE_ENDIAN).getInt(); return sample; } public void setSampleInt(int sampleNumber, int sampleValue) { byte[] sampleBytes = ByteBuffer.allocate(sampleSize). order(ByteOrder.LITTLE_ENDIAN).putInt(sampleValue).array(); for(int i=0; i < sampleSize; i++) { data[sampleNumber * sampleSize + i] = sampleBytes[i]; } } }
      
      







これは、 http://blog.eqlbin.ru/2011/02/wave-java.htmlから取られたわずかに追加されたクラスであることに注意してください。 一般に、ここで追加されるのはgetWave()関数のみです。この関数は、コンストラクターの1つによって構築されたファイルに対応するバイトの配列を返します。 同様に、通常の生ファイルのバイト配列を受け取るコンストラクター。 getWave()関数の結果を正確にStelに送信します。 以下は、 WaveFileを受け入れ、Stelへの接続を開き、必要なものをすべて送信し、接続を閉じて、認識された文字列を返す関数です。



 String getResponseOn(WaveFile wf) { String res = new String(); try { byte[] wav = wf.getWave(); HttpConnection conn = new HttpConnection("api.stel.ru", 7071); conn.open(); HttpState state = new HttpState(); PostMethod post = new PostMethod(); JSONObject data = new JSONObject(); data.put("apikey", "***"); // Place your API key here data.put("model", "rus_gsm_ext"); data.put("wav", new String(Base64.encodeBase64(wav))); post.setPath("/kwfind"); post.setRequestHeader("Content-Type", "application/json"); post.setRequestHeader("Accept", "application/json"); post.setRequestHeader("Content-Length", ""+data.toJSONString().length()); post.setRequestEntity(new StringRequestEntity(data.toJSONString(), "application/json", null)); post.execute(state, conn); res = res + (String) ((JSONObject) new JSONParser().parse(post.getResponseBodyAsString())).get("text"); conn.close(); } catch(Exception e) { res = null; } return res; }
      
      







「***」をキーに置き換える必要があること、およびgetResponseOnWaveFileがパラメーター(2、(float) 8000、1 、(byte [])raw)で作成されることも忘れないでください。例:



 String res1 = getResponseOn(new WaveFile(2, (float) 8000.0, 1, sound)); String res2 = getResponseOn(new WaveFile(new File("test.waw"))); //demo audio file (WAV, 8000 HZ, 16-bit, mono)
      
      







さらに、 getResponseOn(WaveFile wf)org.json.simple.JSONObjectおよびorg.json.simple.parser.JSONParserを使用することに注意する必要があります。これらは、たとえばwww.java2s.com/Code/から個別にダウンロードする必要があります。 Jar / j / Downloadjsonsimple111jar.htm



「Stel」は簡単に連絡を取ることができるため、他の言語や言語ベースが必要な場合は、交渉することができます。



私たちのチームがインテリジェントホームアシスタントLexiを開発していることを思い出してください。 Lexiは、人工知能とスマートホームを制御するための完全な音声インターフェイスを備えたデスクトップデバイスです。 このデバイスは、インターネットで情報を受信したり、家電を制御したり、ソーシャルネットワークからニュースを報告したりできます。 ところで、 この記事では、そのような家庭用ロボットの将来についての興味深い考えについて読むことができます。



ご想像のとおり、音声認識技術はStelaが提供しています。 同時に、音声認識はデバイス上で完全に行われます(当社独自の電子機器の概要については、 こちらをご覧ください )。 これにより、たとえば、ユーザーへの応答の発行速度の向上、アクティベーションフレーズの不在、インターネットなしでの作業能力など、競合製品と比較して多くの利点が得られます。



ソーシャルネットワークのプロジェクトVkontakteFacebookをフォローしてください。



画像

ご清聴ありがとうございました。



All Articles