{"id":299,"date":"2026-02-10T05:40:09","date_gmt":"2026-02-09T20:40:09","guid":{"rendered":"https:\/\/socialakiba.com\/?p=299"},"modified":"2026-02-10T05:43:11","modified_gmt":"2026-02-09T20:43:11","slug":"unreal-%e3%81%8b%e3%82%89-voicevox-%e3%82%92%e3%81%97%e3%82%83%e3%81%b9%e3%82%89%e3%81%9b%e3%82%8b2","status":"publish","type":"post","link":"https:\/\/socialakiba.com\/?p=299","title":{"rendered":"unreal \u304b\u3089 voicevox \u3092\u3057\u3083\u3079\u3089\u305b\u308b2"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">webrick \u3067 ruby\u30b9\u30af\u30ea\u30d7\u30c8\u3067 rest api \u30b5\u30fc\u30d0\u30fc\u3092\u7acb\u3061\u4e0a\u3052\u3066\u3001voicevox \u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u308b\u3088\u3046\u306b\u3057\u305f\uff08powershell \u3067 rest api \u30b5\u30fc\u30d0\u30fc\u3092\u66f8\u3044\u3066\u3044\u305f\u304c\u305d\u308c\u3092\u3084\u3081\u3066 ruby \u3060\u3051\u3067\u66f8\u3044\u305f\uff09\u3002voicevox2.rb<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>require 'net\/http'\nrequire 'uri'\nrequire 'json'\nrequire 'webrick'\n\ndef speak(text, speaker)\n  puts text, speaker\n  uri = URI.parse(\"http:\/\/localhost:50021\/audio_query\")\n  uri.query = URI.encode_www_form({ \"text\" =&gt; text, \"speaker\" =&gt; speaker })\n  headers = {\n    \"Content-Type\" =&gt; \"application\/json\",\n    \"User-Agent\" =&gt; \"vox-client:0.1\",\n  }\n  response = Net::HTTP.post(uri, \"\", headers)\n  case response\n  when Net::HTTPSuccess\n    result = JSON.parse(response.body)\n  else\n    puts \"audio query error: #{response}\"\n  end\n  uri = URI.parse(\"http:\/\/localhost:50021\/synthesis\")\n  uri.query = URI.encode_www_form({ \"speaker\" =&gt; speaker })\n  response = Net::HTTP.post(uri, response.body, headers)\n  if response.code == '200'\n    File.open(\"output#{speaker}.wav\", \"wb\") do |f|\n      f.write(response.body)\n    end\n  else\n    puts \"synthesis response error\"\n  end\nend\n\n# \u30b5\u30fc\u30d0\u30fc\u306e\u8a2d\u5b9a\nserver = WEBrick::HTTPServer.new(\n  Port: 6001,\n  BindAddress: '0.0.0.0'\n)\n\n# POST \/talk \u3068\u3044\u3046\u30d1\u30b9\u3078\u306e\u51e6\u7406\u3092\u5b9a\u7fa9\nserver.mount_proc '\/talk' do |req, res|\n  # POST\u30e1\u30bd\u30c3\u30c9\u4ee5\u5916\u306f\u53d7\u3051\u4ed8\u3051\u306a\u3044\n  if req.request_method == 'POST'\n    begin\n      # 1. \u30ea\u30af\u30a8\u30b9\u30c8\u30dc\u30c7\u30a3\u3092\u8aad\u307f\u8fbc\u3093\u3067JSON\u30d1\u30fc\u30b9\n      data = JSON.parse(req.body)\n      \n      # 2. \"message\" \u30ad\u30fc\u3092\u53d6\u308a\u51fa\u3057\u3066\u8868\u793a\n      message = data&#91;\"message\"]\n      puts \"&#91;#{Time.now}] \u53d7\u4fe1\u30e1\u30c3\u30bb\u30fc\u30b8: #{message}\"\n      speak(message, 1)\n      # powershell \u3067 output*.wav \u3092\u9cf4\u3089\u3059\n      system(\"powershell -ExecutionPolicy Bypass -command .\\\\sound1.ps1\")\n      # 3. \u30b9\u30c6\u30fc\u30bf\u30b9\u30b3\u30fc\u30c9 204 (No Content) \u3092\u8a2d\u5b9a\n      res.status = 204\n    rescue =&gt; e\n      puts \"\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: #{e.message}\"\n      res.status = 400 # \u4e0d\u6b63\u306a\u30ea\u30af\u30a8\u30b9\u30c8\n    end\n  else\n    res.status = 405 # Method Not Allowed\n  end\nend\n\n# Ctrl+C \u3067\u5b89\u5168\u306b\u505c\u6b62\u3059\u308b\u305f\u3081\u306e\u8a2d\u5b9a\ntrap('INT') { server.shutdown }\n\n# \u30b5\u30fc\u30d0\u30fc\u8d77\u52d5\nputs \"Server started on http:\/\/localhost:6001\"\nserver.start\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">ruby (\u3082\u3057\u304f\u306f python) \u3067\u3067\u304d\u308b\u3053\u3068\u306f powershell \u3067\u3084\u308b\u5fc5\u8981\u306f\u7121\u3044\u306a\u3068\u601d\u3046\u3002powershell \u3067\u3057\u304b\u3067\u304d\u306a\u3044\u3053\u3068\uff08windows\u56fa\u6709\u306e\u3001wav\u3092\u518d\u751f\u3059\u308b\u3068\u304b\uff09\u3060\u3051\u3092 powershell \u306b\u6295\u3052\u308c\u3070\u826f\u3044\u306e\u3067\u306f\u306a\u3044\u304b\u3002\u3044\u3084\u3001\u305d\u308c\u304c\u5f53\u305f\u308a\u524d\u306a\u3093\u3060\u308d\u3046\u3051\u3069\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>webrick \u3067 ruby\u30b9\u30af\u30ea\u30d7\u30c8\u3067 rest api \u30b5\u30fc\u30d0\u30fc\u3092\u7acb\u3061\u4e0a\u3052\u3066\u3001voicevox \u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u308b\u3088\u3046\u306b\u3057\u305f\uff08powershell \u3067 rest api \u30b5\u30fc\u30d0\u30fc\u3092\u66f8\u3044\u3066\u3044\u305f\u304c\u305d\u308c\u3092\u3084\u3081\u3066 ruby \u3060 &hellip; <a href=\"https:\/\/socialakiba.com\/?p=299\" class=\"more-link\"><span class=\"screen-reader-text\">&#8220;unreal \u304b\u3089 voicevox \u3092\u3057\u3083\u3079\u3089\u305b\u308b2&#8221; \u306e<\/span>\u7d9a\u304d\u3092\u8aad\u3080<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-299","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/socialakiba.com\/index.php?rest_route=\/wp\/v2\/posts\/299","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/socialakiba.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/socialakiba.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/socialakiba.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/socialakiba.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=299"}],"version-history":[{"count":4,"href":"https:\/\/socialakiba.com\/index.php?rest_route=\/wp\/v2\/posts\/299\/revisions"}],"predecessor-version":[{"id":303,"href":"https:\/\/socialakiba.com\/index.php?rest_route=\/wp\/v2\/posts\/299\/revisions\/303"}],"wp:attachment":[{"href":"https:\/\/socialakiba.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/socialakiba.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/socialakiba.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}