Office関連

モヤさまのショウ君にいろいろ喋らせるVBAマクロ(2)

前回に引き続き、HOYAサービス株式会社様が公開されている「VoiceText Web API」をVBAマクロから使ってみる話です。

このAPIの使い方は前回の記事通りで、基本的にAPIのURLにパラメーターを付けてリクエストを送るだけです。非常に簡単です。

ただ、前回載せたコードは単に動作確認するためのコードなので、今回は使いやすいように引数でパラメーターを指定できるようにしたいと思います。

・・・というわけで、書いたコードが下記になります。

Option Explicit

Private Declare Function mciSendString Lib "winmm" Alias "mciSendStringA" ( _
        ByVal lpstrCommand As String, _
        ByVal lpstrReturnString As String, _
        ByVal uReturnLength As Long, _
        ByVal hwndCallback As Long) As Long

Public Sub Sample()
  PlayVoiceText "あいうえお", "haruka", "happiness", 2, 50, 200, 50
  PlayVoiceText "かきくけこ", "show", , , 150, 400, 200
  PlayVoiceText "さしすせそ", "hikari", "sadness", 1, 140, 300, 80
End Sub

Public Sub PlayVoiceText(ByVal txt As String, _
                         ByVal speaker As String, _
                         Optional ByVal emotion As String = "", _
                         Optional ByVal emotion_level As Long = 1, _
                         Optional ByVal pitch As Long = 100, _
                         Optional ByVal speed As Long = 100, _
                         Optional ByVal volume As Long = 100)
'VoiceText Web APIを使ってテキスト読み上げ
  Dim url As String
  Dim dat As Variant
  Dim body() As Byte
  Dim pathTempFolder As String
  Dim pathWavFile As String
  
  Const adTypeBinary = 1
  Const API_KEY As String = "(APIキー)" 'コードを動かす際はここに受け取ったAPIキーを記載します。
  
  'パラメーターチェック
  txt = DelBreak(txt)
  If Len(txt) < 1 Then
    MsgBox "読み上げるテキストを指定してください。", vbExclamation + vbSystemModal
    Exit Sub
  End If
  If Len(txt) > 200 Then
    MsgBox "読み上げるテキストは200文字以内にしてください。", vbExclamation + vbSystemModal
    Exit Sub
  End If
  speaker = LCase(speaker)
  Select Case speaker
    Case "show", "haruka", "hikari", "takeru"
    Case Else
      MsgBox "「speaker」には" & vbCrLf & vbCrLf & _
             "show" & vbCrLf & _
             "haruka" & vbCrLf & _
             "hikari" & vbCrLf & _
             "takeru" & vbCrLf & vbCrLf & _
             "以外を指定しないでください。", vbExclamation + vbSystemModal
      Exit Sub
  End Select
  '[emotion]を指定できるのは[show]以外
  If speaker <> "show" Then
    emotion = LCase(emotion)
    If Len(emotion) > 0 Then
      Select Case emotion
        Case "happiness", "anger", "sadness"
        Case Else
          MsgBox "「emotion」には" & vbCrLf & vbCrLf & _
                 "happiness" & vbCrLf & _
                 "anger" & vbCrLf & _
                 "sadness" & vbCrLf & vbCrLf & _
                 "以外を指定しないでください。", vbExclamation + vbSystemModal
          Exit Sub
      End Select
      Select Case emotion_level
        Case 1, 2
        Case Else
          MsgBox "「emotion_level」には" & vbCrLf & vbCrLf & _
                   "1" & vbCrLf & _
                   "2" & vbCrLf & vbCrLf & _
                   "以外を指定しないでください。", vbExclamation + vbSystemModal
          Exit Sub
      End Select
    End If
  End If
  Select Case pitch
    Case 50 To 200
    Case Else
      MsgBox "「pitch」に指定できる数値の範囲は" & vbCrLf & vbCrLf & _
               "50 - 200" & vbCrLf & vbCrLf & _
               "です。", vbExclamation + vbSystemModal
      Exit Sub
  End Select
  Select Case speed
    Case 50 To 400
    Case Else
      MsgBox "「speed」に指定できる数値の範囲は" & vbCrLf & vbCrLf & _
               "50 - 400" & vbCrLf & vbCrLf & _
               "です。", vbExclamation + vbSystemModal
      Exit Sub
  End Select
  Select Case volume
    Case 50 To 200
    Case Else
      MsgBox "「volume」に指定できる数値の範囲は" & vbCrLf & vbCrLf & _
               "50 - 200" & vbCrLf & vbCrLf & _
               "です。", vbExclamation + vbSystemModal
      Exit Sub
  End Select
  
  'パラメーター設定
  url = "https://api.voicetext.jp/v1/tts"
  dat = "text=" & EncodeURL(txt) & "&speaker=" & speaker
  If speaker <> "show" Then
    If Len(emotion) > 0 Then
      dat = dat & "&emotion=" & emotion
      dat = dat & "&emotion_level=" & emotion_level
    End If
  End If
  dat = dat & "&pitch=" & pitch
  dat = dat & "&speed=" & speed
  dat = dat & "&volume=" & volume
  'Debug.Print dat '確認用
  
  'wavファイルパス設定
  pathTempFolder = GetTempFolderPath
  If Len(Trim(pathTempFolder)) < 1 Then Exit Sub
  pathTempFolder = AddPathSeparator(pathTempFolder)
  pathWavFile = pathTempFolder & "VtwaFile.wav"
  
  'wavファイルを事前に削除
  If ChkExistsFile(pathWavFile) = True Then DelFile pathWavFile
  
  On Error GoTo Err:
  With CreateObject("WinHttp.WinHttpRequest.5.1")
    .Open "POST", url, False
    .SetRequestHeader "Authorization", "Basic " & EncodeBase64Str(API_KEY & ":")
    .SetRequestHeader "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"
    .Send dat
    Select Case .Status
      Case 200
        body = .responseBody
        With CreateObject("ADODB.Stream")
          .Type = adTypeBinary
          .Open
          .Write body
          .SaveToFile pathWavFile
          .Close
        End With
        If ChkExistsFile(pathWavFile) = True Then
          'wavファイル再生
          mciSendString "Open " & Chr(34) & pathWavFile & Chr(34), "", 0, 0
          mciSendString "Play " & Chr(34) & pathWavFile & Chr(34) & " wait", "", 0, 0
          mciSendString "Close " & Chr(34) & pathWavFile & Chr(34), "", 0, 0
          DelFile pathWavFile 'wavファイル削除
          'Debug.Print "処理が終了しました。" '確認用
        End If
      Case Else
        MsgBox "処理が失敗しました。" & vbCrLf & vbCrLf & .ResponseText, vbExclamation + vbSystemModal
        Exit Sub
    End Select
  End With
  On Error GoTo 0
  Exit Sub
  
Err:
  MsgBox "エラーが発生しました。" & vbCrLf & _
         "エラー番号:" & Err.Number & vbCrLf & _
         "エラー内容:" & Err.Description, vbCritical + vbSystemModal
End Sub

Private Sub DelFile(ByVal FilePath As String)
'ファイル削除
  CreateObject("Scripting.FileSystemObject").DeleteFile FilePath, True
End Sub

Private Function GetTempFolderPath() As String
'Tempフォルダのパス取得
  Dim ret As String
  
  ret = "" '初期化
  On Error Resume Next
  ret = CreateObject("Scripting.FileSystemObject").GetSpecialFolder(2)
  On Error GoTo 0
  GetTempFolderPath = ret
End Function

Private Function AddPathSeparator(ByVal str As String) As String
'パスの区切り文字追加
  If Right(str, 1) <> ChrW(92) Then str = str & ChrW(92)
  AddPathSeparator = str
End Function

Private Function ChkExistsFile(ByVal FilePath As String) As Boolean
'ファイルの存在確認
  Dim ret As Boolean
  
  ret = False '初期化
  With CreateObject("Scripting.FileSystemObject")
    ret = .FileExists(FilePath)
  End With
  ChkExistsFile = ret
End Function

Private Function DelBreak(ByVal str As String) As String
'改行削除
  Dim ret As String
  
  ret = "" '初期化
  ret = Replace(str, vbNewLine, "")
  ret = Replace(ret, vbCr, "")
  ret = Replace(ret, vbLf, "")
  DelBreak = ret
End Function

Private Function EncodeURL(ByVal str As String) As String
'URLエンコード
  With CreateObject("ScriptControl")
    .Language = "JScript"
    EncodeURL = .CodeObject.encodeURIComponent(str)
  End With
End Function

Private Function EncodeBase64Str(ByVal str As String) As String
'文字列をBase64エンコード
  Dim ret As String
  Dim d() As Byte
  
  Const adTypeBinary = 1
  Const adTypeText = 2
  
  ret = "" '初期化
  On Error Resume Next
  With CreateObject("ADODB.Stream")
    .Open
    .Type = adTypeText
    .Charset = "UTF-8"
    .WriteText str
    .Position = 0
    .Type = adTypeBinary
    .Position = 3
    d = .Read()
    .Close
  End With
  With CreateObject("MSXML2.DOMDocument").createElement("base64")
    .DataType = "bin.base64"
    .nodeTypedValue = d
    ret = .Text
  End With
  On Error GoTo 0
  EncodeBase64Str = ret
End Function

冗長なコードになってしまいましたが、やっていることは引数として受け取ったパラメーターをリクエストにくっつけて、受け取ったwavファイルをmciSendStringで再生しているだけです。

今回のコードも、そのままでは64ビット版のOfficeで動作しませんので、64ビット版Officeをお使いの方は注意してください。
(コード中、DirやKillを使っていないのは、単にVBScriptに移植しやすいようにしているだけです。)

何はともあれ、これでVBAからVoiceText Web APIが使いやすくなりました。
コードを追加すれば、Wordでショウ君に選択範囲を読み上げてもらったり、Excelの選択セルの内容をショウ君に読み上げてもらったりすることができます。

200文字という制限はありますが、十分にVoiceTextの性能の素晴らしさを実感することができます。

2014年8月時点ではまだβ版ということで、今後サービスの停止や有料化することも考えられますが、今はまだ遊べます試用できますので、興味がある方は是非一度お試しください。

モヤさまのショウ君にいろいろ喋らせるVBAマクロ(1)前のページ

テキスト比較ソフト「ちゃうちゃう!」がバージョンアップされました。次のページ

関連記事

  1. Office関連

    PDFファイル上のフィールドの値を操作するVBAマクロ

    「PDFファイルに差し込み印刷するVBAマクロ」で、Acrobatを操…

  2. Office関連

    MDB(Accessデータベース)ファイルを作成してデータを格納するExcelマクロ

    2012/2/22追記:下記で作成したMDBファイルを利用したWo…

  3. Office関連

    「NetOffice」で簡単に.NETからOfficeを操作

    ネットで「NetOffice」なるツールがあることを知ったので、早速試…

  4. Office関連

    [OneNote]クリップボードから新しいページに貼り付け

    何かをメモするとき、ファイルを保存するとき等々、私はよくOneNote…

  5. Office関連

    Office製品のフィードバックって本当に反映されるの?

    今年の1月に、WordやExcel等のOffice製品で、UI上の不具…

  6. Office関連

    UI Automationの参考資料

    VBAからUI Automationを扱う際に参考になりそうな資料への…

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

Time limit is exhausted. Please reload CAPTCHA.

※本ページはプロモーションが含まれています。

Translate

最近の記事

アーカイブ

PAGE TOP