diff --git a/iOS/Ringo/Ringo.xcodeproj/project.pbxproj b/iOS/Ringo/Ringo.xcodeproj/project.pbxproj index f5dac05..39b7997 100644 --- a/iOS/Ringo/Ringo.xcodeproj/project.pbxproj +++ b/iOS/Ringo/Ringo.xcodeproj/project.pbxproj @@ -40,6 +40,7 @@ 945CF9872B67E1CE00396E4E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 945CF9852B67E1CE00396E4E /* LaunchScreen.storyboard */; }; 945CF9902B69341800396E4E /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 945CF98F2B69341800396E4E /* SnapKit */; }; 94FB0A6B2B858F66005A4915 /* TestSTTViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94FB0A6A2B858F66005A4915 /* TestSTTViewController.swift */; }; + 94FB0A6D2BAAD64A005A4915 /* TTS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94FB0A6C2BAAD64A005A4915 /* TTS.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -74,6 +75,7 @@ 945CF9862B67E1CE00396E4E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 945CF9882B67E1CE00396E4E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 94FB0A6A2B858F66005A4915 /* TestSTTViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSTTViewController.swift; sourceTree = ""; }; + 94FB0A6C2BAAD64A005A4915 /* TTS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TTS.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -176,6 +178,7 @@ 940C25652B74EF4D00E069D0 /* FriendService.swift */, 94470A962B717DC300F0A942 /* ConnectionViewController.swift */, 94FB0A6A2B858F66005A4915 /* TestSTTViewController.swift */, + 94FB0A6C2BAAD64A005A4915 /* TTS.swift */, 945603202B6D2F06002F4B33 /* Canvas.swift */, 945CF9832B67E1CE00396E4E /* Assets.xcassets */, 945CF9852B67E1CE00396E4E /* LaunchScreen.storyboard */, @@ -273,6 +276,7 @@ 940C25852B7A89AB00E069D0 /* NativeWebSocket.swift in Sources */, 945CF97F2B67E1CD00396E4E /* ViewController.swift in Sources */, 940C25642B73D20900E069D0 /* ConnectionCollectionViewCell.swift in Sources */, + 94FB0A6D2BAAD64A005A4915 /* TTS.swift in Sources */, 940C257A2B7A899500E069D0 /* IceCandidate.swift in Sources */, 945603192B6AC365002F4B33 /* AccountViewController.swift in Sources */, 940C258A2B7A8FA900E069D0 /* CallService.swift in Sources */, diff --git a/iOS/Ringo/Ringo.xcodeproj/project.xcworkspace/xcuserdata/jinhyuk.xcuserdatad/UserInterfaceState.xcuserstate b/iOS/Ringo/Ringo.xcodeproj/project.xcworkspace/xcuserdata/jinhyuk.xcuserdatad/UserInterfaceState.xcuserstate index b0c9c65..a291b42 100644 Binary files a/iOS/Ringo/Ringo.xcodeproj/project.xcworkspace/xcuserdata/jinhyuk.xcuserdatad/UserInterfaceState.xcuserstate and b/iOS/Ringo/Ringo.xcodeproj/project.xcworkspace/xcuserdata/jinhyuk.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/iOS/Ringo/Ringo/Screens/ContactsViewController.swift b/iOS/Ringo/Ringo/Screens/ContactsViewController.swift index ac5f03f..f8be11a 100644 --- a/iOS/Ringo/Ringo/Screens/ContactsViewController.swift +++ b/iOS/Ringo/Ringo/Screens/ContactsViewController.swift @@ -52,7 +52,7 @@ class ContactsViewController: UIViewController { @objc private func test() { DispatchQueue.global().async { - CallService.shared.signalClient.store(id: "asdfg@naver.com") + CallService.shared.signalClient.store(id: "rkdwlsgur@naver.com") } } } @@ -114,7 +114,7 @@ extension ContactsViewController { func loadFriends() { //id ??인 유저의 친구목록 - FriendService.shared.loadFriendsList(userId: 2) { response in + FriendService.shared.loadFriendsList(userId: 10) { response in switch response { case .success(let data): @@ -145,7 +145,7 @@ extension ContactsViewController { extension ContactsViewController: ContactsTableViewCellDelegate { func pressedButton() { - CallService.shared.signalClient.startcall(id: "2", target: "1") + CallService.shared.signalClient.startcall(id: "10", target: "8") } } diff --git a/iOS/Ringo/Ringo/Screens/TabBarViewController.swift b/iOS/Ringo/Ringo/Screens/TabBarViewController.swift index ac42076..427f5c8 100644 --- a/iOS/Ringo/Ringo/Screens/TabBarViewController.swift +++ b/iOS/Ringo/Ringo/Screens/TabBarViewController.swift @@ -68,7 +68,7 @@ extension TabBarViewController: SignalClientDelegate { func signalClient(_ signalClient: SignalingClient, didReceiveCallResponse response: String) { if response == "user is ready for call" { CallService.shared.webRTCClient.offer { (sdp) in - var message = Message(type: .create_offer, name: "asdfg@naver.com", target: "asdf@naver.com") + var message = Message(type: .create_offer, name: "rkdwlsgur@naver.com", target: "rkdwltjr@naver.com") message.data = .sdp(SessionDescription(from: sdp)) CallService.shared.signalClient.send(message: message) } @@ -83,9 +83,14 @@ extension TabBarViewController: SignalClientDelegate { } } + func signalClient(_ signalClient: SignalingClient, didReceiveTranslation msg: String, language: String) { + TTS.shared.play(msg, language) + TTS.shared.stop() + } + func acceptCall() { CallService.shared.webRTCClient.answer { (localSdp) in - var message = Message(type: .create_answer, name: "asdfg@naver.com", target: "asdf@naver.com") + var message = Message(type: .create_answer, name: "rkdwlsgur@naver.com", target: "rkdwltjr@naver.com") message.data = .sdp(SessionDescription(from: localSdp)) CallService.shared.signalClient.send(message: message) // CallService.shared.signalClient.send(sdp: localSdp) @@ -100,7 +105,7 @@ extension TabBarViewController: SignalClientDelegate { extension TabBarViewController: WebRTCClientDelegate { func webRTCClient(_ client: WebRTCClient, didDiscoverLocalCandidate candidate: RTCIceCandidate) { print("discovered local candidate") - var message = Message(type: .ice_candidate, name: "asdfg@naver.com", target: "asdf@naver.com") + var message = Message(type: .ice_candidate, name: "rkdwlsgur@naver.com", target: "rkdwltjr@naver.com") message.data = .candidate(IceCandidate(from: candidate)) CallService.shared.signalClient.send(message: message) // CallService.shared.signalClient.send(candidate: candidate) diff --git a/iOS/Ringo/Ringo/TTS.swift b/iOS/Ringo/Ringo/TTS.swift new file mode 100644 index 0000000..398fd4c --- /dev/null +++ b/iOS/Ringo/Ringo/TTS.swift @@ -0,0 +1,28 @@ +// +// TTS.swift +// Ringo +// +// Created by 강진혁 on 3/20/24. +// + +import Foundation +import AVFoundation + +class TTS { + static let shared = TTS() + + private let synthesizer = AVSpeechSynthesizer() + + internal func play(_ string: String, _ language: String) { + let utterance = AVSpeechUtterance(string: string) + utterance.voice = AVSpeechSynthesisVoice(language: language) + utterance.rate = 0.4 + synthesizer.stopSpeaking(at: .immediate) + synthesizer.speak(utterance) + } + + internal func stop() { + synthesizer.stopSpeaking(at: .immediate) + } + +} diff --git a/iOS/Ringo/Ringo/TestSTTViewController.swift b/iOS/Ringo/Ringo/TestSTTViewController.swift index 5bbecda..1d3b49f 100644 --- a/iOS/Ringo/Ringo/TestSTTViewController.swift +++ b/iOS/Ringo/Ringo/TestSTTViewController.swift @@ -129,6 +129,13 @@ class TestSTTViewController: UIViewController, SFSpeechRecognizerDelegate { // Update the text view with the results. self.textView.text = result.bestTranscription.formattedString isFinal = result.isFinal + debugPrint(result.bestTranscription.formattedString) + if result.speechRecognitionMetadata != nil { + var message = Message(type: .stt_message, name: "rkdwlsgur@naver.com", target: "rkdwltjr@naver.com") + message.data = .response(result.bestTranscription.formattedString) + CallService.shared.signalClient.send(message: message) + debugPrint("send trans msg") + } } if error != nil || isFinal { diff --git a/iOS/Ringo/Ringo/WebRTC/Extensions/SessionDescription.swift b/iOS/Ringo/Ringo/WebRTC/Extensions/SessionDescription.swift index 1557ed1..e010fa6 100644 --- a/iOS/Ringo/Ringo/WebRTC/Extensions/SessionDescription.swift +++ b/iOS/Ringo/Ringo/WebRTC/Extensions/SessionDescription.swift @@ -11,12 +11,12 @@ import WebRTC /// This enum is a swift wrapper over `RTCSdpType` for easy encode and decode enum SdpType: String, Codable { - case OFFER, prAnswer, answer, rollback + case OFFER, prAnswer, ANSWER, rollback var rtcSdpType: RTCSdpType { switch self { case .OFFER: return .offer - case .answer: return .answer + case .ANSWER: return .answer case .prAnswer: return .prAnswer case .rollback: return .rollback } @@ -34,7 +34,7 @@ struct SessionDescription: Codable { switch rtcSessionDescription.type { case .offer: self.type = .OFFER case .prAnswer: self.type = .prAnswer - case .answer: self.type = .answer + case .answer: self.type = .ANSWER case .rollback: self.type = .rollback @unknown default: fatalError("Unknown RTCSessionDescription type: \(rtcSessionDescription.type.rawValue)") diff --git a/iOS/Ringo/Ringo/WebRTC/Services/Message.swift b/iOS/Ringo/Ringo/WebRTC/Services/Message.swift index 7d208d0..12e0a44 100644 --- a/iOS/Ringo/Ringo/WebRTC/Services/Message.swift +++ b/iOS/Ringo/Ringo/WebRTC/Services/Message.swift @@ -53,7 +53,7 @@ import Foundation struct Message: Codable { enum MessageType: String, Codable { - case call_response, create_offer, offer_received, create_answer, answer_received, ice_candidate, start_call + case call_response, create_offer, offer_received, create_answer, answer_received, ice_candidate, start_call, stt_message, translate_message } enum DataType { @@ -90,7 +90,7 @@ struct Message: Codable { self.name = try? container.decode(String.self, forKey: .name) self.target = try? container.decode(String.self, forKey: .target) switch type { - case .call_response: + case .call_response,.stt_message,.translate_message: self.data = .response(try container.decode(String.self, forKey: .data)) case .create_offer,.offer_received,.create_answer,.answer_received: debugPrint("sdp") diff --git a/iOS/Ringo/Ringo/WebRTC/Services/SignalingClient.swift b/iOS/Ringo/Ringo/WebRTC/Services/SignalingClient.swift index 14fcd87..44a143b 100644 --- a/iOS/Ringo/Ringo/WebRTC/Services/SignalingClient.swift +++ b/iOS/Ringo/Ringo/WebRTC/Services/SignalingClient.swift @@ -15,6 +15,7 @@ protocol SignalClientDelegate: AnyObject { func signalClient(_ signalClient: SignalingClient, didReceiveRemoteSdp sdp: RTCSessionDescription) func signalClient(_ signalClient: SignalingClient, didReceiveCandidate candidate: RTCIceCandidate) func signalClient(_ signalClient: SignalingClient, didReceiveCallResponse response: String) + func signalClient(_ signalClient: SignalingClient, didReceiveTranslation msg: String, language: String) } final class SignalingClient { @@ -135,11 +136,11 @@ extension SignalingClient: WebSocketProviderDelegate { switch message.type { case .call_response: debugPrint("call_response") - debugPrint(message) +// debugPrint(message) self.delegate?.signalClient(self, didReceiveCallResponse: message.dataString()) case .offer_received,.answer_received: debugPrint("received") - debugPrint(message) +// debugPrint(message) switch message.data { case .sdp(let sessionDescription): self.delegate?.signalClient(self, didReceiveRemoteSdp: sessionDescription.rtcSessionDescription) @@ -148,13 +149,17 @@ extension SignalingClient: WebSocketProviderDelegate { } case .ice_candidate: debugPrint("ice_candidate") - debugPrint(message) +// debugPrint(message) switch message.data { case .candidate(let iceCandidate): self.delegate?.signalClient(self, didReceiveCandidate: iceCandidate.rtcIceCandidate) default: print("????") } + case .translate_message: + debugPrint("receive trans msg") + debugPrint(message) + self.delegate?.signalClient(self, didReceiveTranslation: message.dataString(), language: message.target!) default: debugPrint("message.type is nothing") debugPrint(message)