iPhone版 話して!(その2)
OpenAIのGPT-4を使ってApp Inventor 2日本語版のチュートリアルにあるアプリと同じように動くiPhoneアプリを作ります。iPhoneアプリを作るにはMacで動くXcodeという開発環境が必要です。ここではmacOS 13.2.1上でXcode 14.3を使っています。このアプリではスマホを振るというジェスチャーを使うので、動作確認にはiPhone 11実機(iOS 16.4.1)を使いました。
準備
iPhone版 話して!(その1)を動くようにする
iPhone版 話して!(その1)のコードはiOSシミュレータでは動くもののiPhone 11実機では声が聞こえなかったので、以下のようにコードを修正しました。AVAudioSessionをリセットする部分を追加しています。GPT-4に聞いたのですが日本語ではなかなか動くコードを作れなかったので、英語でいろいろ試して最終的にこのコードで動きました。
import SwiftUI
import AVFoundation
struct ContentView: View {
@State private var speechSynthesizer = AVSpeechSynthesizer()
var body: some View {
VStack {
Button(action: {
self.configureAudioSession()
self.speakText("今日は新宿で映画を見よう")
}) {
Text("話して!")
.font(.title)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
}
func configureAudioSession() {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.playback, mode: .spokenAudio, options: [])
try audioSession.setActive(true, options: [])
} catch {
print("Failed to configure audio session: \(error.localizedDescription)")
}
}
func speakText(_ text: String) {
let utterance = AVSpeechUtterance(string: text)
utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
speechSynthesizer.speak(utterance)
}
}
iPhoneの振るジェスチャーを無効にする
iPhoneではデフォルトで振るジェスチャーは入力取り消しをするので、これを以下の手順で無効にします。
iPhoneの設定->アクセシビリティ->タッチ->シェイクで取り消しをOFF
GPT-4とのやり取り
プロンプト
このコードにスマホを振るとテキストフィールドに入力された言葉を話す機能を追加して
import SwiftUI
import AVFoundation
struct ContentView: View {
@State private var speechSynthesizer = AVSpeechSynthesizer()
var body: some View {
VStack {
Button(action: {
self.configureAudioSession()
self.speakText("今日は新宿で映画を見よう")
}) {
Text("話して!")
.font(.title)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
}
func configureAudioSession() {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.playback, mode: .spokenAudio, options: [])
try audioSession.setActive(true, options: [])
} catch {
print("Failed to configure audio session: \(error.localizedDescription)")
}
}
func speakText(_ text: String) {
let utterance = AVSpeechUtterance(string: text)
utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
speechSynthesizer.speak(utterance)
}
}
返答
以下のコードは、スマホを振ることでテキストフィールドに入力された言葉を話す機能が追加されたものです。
CoreMotion
フレームワークを使用し、加速度センサーのデータを取得してスマホが振られたかどうかを判断します。
import SwiftUI
import AVFoundation
import CoreMotion
struct ContentView: View {
@State private var speechSynthesizer = AVSpeechSynthesizer()
@State private var motionManager = CMMotionManager()
@State private var text = ""
var body: some View {
VStack {
TextField("ここにテキストを入力してください", text: $text)
.padding()
.textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: {
self.configureAudioSession()
self.speakText(text)
}) {
Text("話して!")
.font(.title)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
.onAppear {
self.startMonitoringShakeGesture()
}
.onDisappear {
self.stopMonitoringShakeGesture()
}
}
}
func configureAudioSession() {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.playback, mode: .spokenAudio, options: [])
try audioSession.setActive(true, options: [])
} catch {
print("Failed to configure audio session: \(error.localizedDescription)")
}
}
func speakText(_ text: String) {
let utterance = AVSpeechUtterance(string: text)
utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
speechSynthesizer.speak(utterance)
}
func startMonitoringShakeGesture() {
guard motionManager.isAccelerometerAvailable else { return }
motionManager.accelerometerUpdateInterval = 0.1
motionManager.startAccelerometerUpdates(to: OperationQueue.current!) { (data, error) in
guard let data = data, error == nil else { return }
if abs(data.acceleration.x) > 2.5 || abs(data.acceleration.y) > 2.5 || abs(data.acceleration.z) > 2.5 {
self.configureAudioSession()
self.speakText(text)
}
}
}
func stopMonitoringShakeGesture() {
motionManager.stopAccelerometerUpdates()
}
}
このコードは、入力されたテキストを話す機能と、スマホを振るとテキストを話す機能を含んでいます。テキストフィールドが追加され、
startMonitoringShakeGesture()
およびstopMonitoringShakeGesture()
を使って、画面が表示される時と消える時にシェイクジェスチャーの監視を開始および停止します。
プロンプト
ボタンをクリックしたら「今日は新宿で映画を見よう」と話して、スマホを振ったらテキストフィールドのテキストを話すように変更して。
返答
以下のコードは、ボタンをクリックすると「今日は新宿で映画を見よう」と話し、スマホを振るとテキストフィールドに入力された言葉を話すように変更されています。
import SwiftUI
import AVFoundation
import CoreMotion
struct ContentView: View {
@State private var speechSynthesizer = AVSpeechSynthesizer()
@State private var motionManager = CMMotionManager()
@State private var text = ""
var body: some View {
VStack {
TextField("ここにテキストを入力してください", text: $text)
.padding()
.textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: {
self.configureAudioSession()
self.speakText("今日は新宿で映画を見よう")
}) {
Text("話して!")
.font(.title)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
.onAppear {
self.startMonitoringShakeGesture()
}
.onDisappear {
self.stopMonitoringShakeGesture()
}
}
}
func configureAudioSession() {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.playback, mode: .spokenAudio, options: [])
try audioSession.setActive(true, options: [])
} catch {
print("Failed to configure audio session: \(error.localizedDescription)")
}
}
func speakText(_ text: String) {
let utterance = AVSpeechUtterance(string: text)
utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
speechSynthesizer.speak(utterance)
}
func startMonitoringShakeGesture() {
guard motionManager.isAccelerometerAvailable else { return }
motionManager.accelerometerUpdateInterval = 0.1
motionManager.startAccelerometerUpdates(to: OperationQueue.current!) { (data, error) in
guard let data = data, error == nil else { return }
if abs(data.acceleration.x) > 2.5 || abs(data.acceleration.y) > 2.5 || abs(data.acceleration.z) > 2.5 {
self.configureAudioSession()
self.speakText(text)
}
}
}
func stopMonitoringShakeGesture() {
motionManager.stopAccelerometerUpdates()
}
}
この変更により、ボタンをクリックすると「今日は新宿で映画を見よう」と話し、スマホを振るとテキストフィールドに入力された言葉を話すようになります。
XcodeでiPhoneアプリを作る
プロジェクトの作成
Xcodeを起動してTalkToMe-2という名前のiOS Appプロジェクトを作ります。InterfaceはSwiftUIでLanguageはSwiftにします。
swiftコードの貼り付け
GPT-4が作ってくれたswiftのコードをContentView.swiftに貼り付けます。
調整としてstartMonitoringShakeGestureの中の2.5をすべて2.0に変更します。
実行
実行結果はこの通り。下の画像をクリックしてYouTubeデモビデオを見てください。