1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RubyでOpenAIのSpeech APIを読んで、mp3を出力する簡単なコマンドラインツールのスクリプト

Last updated at Posted at 2024-11-10

はじめに

標準入力やファイルを引数にとって、mp3を出力したい。
ChatGPT API課金勢なら、OpenAIのAPI叩くのが一番簡単。

echo "この文章をスピーチして" | speech.rb -o out.mp3

gistでもいいのだが、検索しにくいのでQiita。

使うもの

スクリプト本体

speech.rb
#! /usr/bin/env ruby

require 'optparse'
require 'openai'
require 'whirly'

options = {
  output: 'speech',
  model: 'tts-1',
  voice: 'alloy',
  response_format: 'mp3',
  speed: '1.0',
  input: nil
}

OptionParser.new do |opts|
  opts.banner = "Usage: #{File.basename($0)} [options]"

  opts.on('-o', '--output FILE', '出力ファイル名(拡張子なし) [speech]') do |v|
    options[:output] = v
  end

  opts.on('-m', '--model MODEL', '使用するモデル [tts-1] tts-1-hd') do |v|
    options[:model] = v
  end

  opts.on('-i', '--input FILE', '入力テキスト') do |v|
    options[:input] = v
  end

  opts.on('-v', '--voice VOICE', '使用するボイス [alloy] echo fable onyx nova shimmer') do |v|
    options[:voice] = v
  end

  opts.on('-f', '--response-format FORMAT', '出力形式 [mp3] opus aac flac wav pcm') do |v|
    options[:response_format] = v
  end

  opts.on('-s', '--speed SPEED', '読み上げ速度 [1.0] 0.25 - 4.0') do |v|
    options[:speed] = v
  end

  opts.on('-h', '--help', 'このヘルプメッセージを表示') do
    puts opts
    exit
  end
end.parse!

options[:input] ||= ARGF.read

client = OpenAI::Client.new(access_token: ENV['OPENAI_API_KEY'])

Whirly.start spinner: 'dots', remove_after_stop: true
response = client.audio.speech(
  parameters: {
    model: options[:model],
    input: options[:input],
    voice: options[:voice],
    response_format: options[:response_format],
    speed: options[:speed]
  }
)

File.binwrite("#{options[:output]}.#{options[:response_format]}", response)
Whirly.stop

感想など

Rubyはこういうスクリプトがさくっとかけて助かる。

Crystalが好きなので、Crystalで実装したかったけど、ライブラリに自分でSpeech APIを追加するのが面倒くさかったのでRubyにした。ruby-openai の実装がどうなっているか確認したけれども、パラメータやレスポンスはクラスで固めておらず、将来OpenAI側のAPIが変更されても動くようになっている。Crystalのような静的言語は、かちっと構造体にする実装を選ばざるをえないことが多く、脆い。その点、動的言語はロバストなところがいい。

こういうの見ていても、静的言語がどんなときも動的言語の上位互換という話はないよなあと思う。(僕はCrystal大好きですが)

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?