본문에 일부 태그 오류가 있습니다. 동영상 강의를 참고하여 실습해 주시기 바랍니다.
안녕하세요. 언제나 휴일, 언휴예요.
이전 강의에서 Kakao API를 이용하여 번역 라이브러리를 만들었어요.
이번 강의에서는 .NET 음성 Speech 기술을 접목하여 WrapSpeechLib를 만들어 봅시다.
WrapSpeechLib에는 입력한 내용을 번역하여 읽어주는 Narrator 클래스를 정의할 거예요.
이전 강의에서 만든 WrapKakaoLib 어셈블리와 System.Speech 어셈블리를 참조하세요.
작성할 클래스는 Narrator라고 정할게요.
public class Narrator { }
정적 멤버로 소리를 내는 speecher 개체를 생성합니다.
static SpeechSynthesizer speecher = new SpeechSynthesizer();
정적 생성자에서 시스템에 설치 상태인 음성 개체를 조사하여 지역 정보와 함께 사전 개체에 보관할게요.
이번 강의에서는 지역 정보가 “ko-KR”, “en-US”인 것만 보관합니다.
static Dictionary<LanguageInfo, InstalledVoice> voice_dics = new Dictionary<LanguageInfo, InstalledVoice>(); static Narrator() { foreach (InstalledVoice voice in speecher.GetInstalledVoices()) { if (voice.VoiceInfo.Culture.Name == "en-US") { voice_dics[LanguageInfo.en] = voice; } if (voice.VoiceInfo.Culture.Name == "ko-KR") { voice_dics[LanguageInfo.kr] = voice; } } }
시스템에 설치된 음성 정보를 바탕으로 기본 나래이터 컬렉션을 제공하는 정적 속성을 제공합시다.
public static List Narrators { get { int max = (int)LanguageInfo.MAX_LI; List narrators = new List(); Narrator narrator; for (int i = 0; i < max; i++) { narrator = MakeNarator((LanguageInfo)i); if (narrator != null) { narrators.Add(narrator); } } return narrators; } } /// /// "나래이터 생성" 정적 메서드 /// ///지역 정보 /// 나래이터 public static Narrator MakeNarator(LanguageInfo li) { if (voice_dics.ContainsKey(li)) { return new Narrator(voice_dics[li]); } return null; } public Narrator(InstalledVoice ivoice) { }
설치 상태인 음성 개체를 입력 인자로 받는 생성자를 구현합시다.
생성자에서 화자 이름과 지역 정보 및 인사말을 설정합시다. 인사말은 화자를 소개하는 문구로 사용하는 곳에서 변경할 수 있게 제공할게요. 그리고 이러한 속성 외에 지역 정보에 관한 속성들도 제공합시다.
public string Name { get; private set; } public CultureInfo CultureInfo { get; private set; } public string Introduce_msg { get; set; } public string CultureName { get { return CultureInfo.Name; } } public string DisplayName { get { return CultureInfo.DisplayName; } } public Narrator(InstalledVoice ivoice) { Name = ivoice.VoiceInfo.Name; //speecher.SelectVoice(Name); CultureInfo = ivoice.VoiceInfo.Culture; Introduce_msg = string.Format("안녕하세요. 저의 이름은 {0}입니다.", Name); }
입력받은 내용을 말하는 메서들 제공합시다. 지역 정보가 한국일 때는 그냥 말합니다. 만약 “en-US”라면 번역 후에 말합니다. 강의에서는 한국어와 영어만 제공합니다.
public void Speak(string msg) { speecher.SelectVoice(Name); if (CultureInfo.Name == "ko-KR") { speecher.Speak(msg); } else if (CultureInfo.Name == "en-US") { string result = KakaoTransAPI.Translate(msg); speecher.Speak(result); } }
비동기 메서드도 제공해야 블로킹을 해결할 수 있어요.
public void SpeakAsync(string msg) { speecher.SelectVoice(Name); if (CultureInfo.Name == "ko-KR") { speecher.SpeakAsync(msg); } else if (CultureInfo.Name == "en-US") { string result = KakaoTransAPI.Translate(msg); speecher.SpeakAsync(result); } }
소개하는 메서드도 제공합시다.
public void Introduce() { Speak(Introduce_msg); } public void IntroduceAsync() { SpeakAsync(Introduce_msg); }
다음은 Narrator.cs 소스 코드입니다.
using System.Collections.Generic; using System.Globalization; using System.Speech.Synthesis; using WrapKakaoLib; namespace WrapSpeechLib { /// /// 번역 나래이터 클래스 /// public class Narrator { static SpeechSynthesizer speecher = new SpeechSynthesizer(); static Dictionary<LanguageInfo, InstalledVoice> voice_dics = new Dictionary<LanguageInfo, InstalledVoice>(); static Narrator() { foreach (InstalledVoice voice in speecher.GetInstalledVoices()) { if (voice.VoiceInfo.Culture.Name == "en-US") { voice_dics[LanguageInfo.en] = voice; } if (voice.VoiceInfo.Culture.Name == "ko-KR") { voice_dics[LanguageInfo.kr] = voice; } } } /// /// 나래이터 이름 - 가져오기 /// public string Name { get; private set; } /// /// 나래이터 지역 정보 - 가져오기 /// public CultureInfo CultureInfo { get; private set; } /// /// 인사말 - 가져오기 및 설정하기 /// public string Introduce_msg { get; set; } /// /// 지역화 이름 - 가져오기 /// public string CultureName { get { return CultureInfo.Name; } } /// /// 지역화 디스플레이 이름 - 가져오기 /// public string DisplayName { get { return CultureInfo.DisplayName; } } /// /// 나래이터 생성자 /// ///설치된 음성 public Narrator(InstalledVoice ivoice) { Name = ivoice.VoiceInfo.Name; //speecher.SelectVoice(Name); CultureInfo = ivoice.VoiceInfo.Culture; Introduce_msg = string.Format("안녕하세요. 저의 이름은 {0}입니다.", Name); } /// /// "소개하다." 메서드 /// public void Introduce() { Speak(Introduce_msg); } /// /// "소개하다." 비동기 메서드 /// public void IntroduceAsync() { SpeakAsync(Introduce_msg); } /// /// "말하다." 메서드 /// ///말할 내용 public void Speak(string msg) { speecher.SelectVoice(Name); if (CultureInfo.Name == "ko-KR") { speecher.Speak(msg); } else if (CultureInfo.Name == "en-US") { string result = KakaoTransAPI.Translate(msg); speecher.Speak(result); } } /// /// "말하다." 비동기 메서드 /// /// public void SpeakAsync(string msg) { speecher.SelectVoice(Name); if (CultureInfo.Name == "ko-KR") { speecher.SpeakAsync(msg); } else if (CultureInfo.Name == "en-US") { string result = KakaoTransAPI.Translate(msg); speecher.SpeakAsync(result); } } /// /// 라이브러리 제공 나래이터 컬렉션 - 가져오기 /// public static List Narrators { get { int max = (int)LanguageInfo.MAX_LI; List narrators = new List(); Narrator narrator; for (int i = 0; i < max; i++) { narrator = MakeNarator((LanguageInfo)i); if (narrator != null) { narrators.Add(narrator); } } return narrators; } } /// /// "나래이터 생성" 정적 메서드 /// ///지역 정보 /// 나래이터 public static Narrator MakeNarator(LanguageInfo li) { if (voice_dics.ContainsKey(li)) { return new Narrator(voice_dics[li]); } return null; } /// /// ToString 재정의 /// /// 이름+디스플레이 이름 public override string ToString() { return string.Format("{0}:{1}", Name, DisplayName); } } }
다음은 테스트 코드입니다.
/*https://ehpub.co.kr *카오 번역 API와 .NET 음성 Speech 기술을 Mash-up *** *번역 나래이터 만들기 - 언제나 WPF 프로젝트 ******** *2. WrapSpeechLib ************************* */ using System; using System.Collections.Generic; using WrapSpeechLib; namespace WrapNarrator_예광탄 { class Program { static void Main(string[] args) { Console.ReadLine(); List narrators = Narrator.Narrators; foreach (Narrator narrator in narrators) { narrator.Introduce(); } Console.WriteLine("원하는 문장을 입력하면 읽어주고 번역도 해 줘요."); string str = string.Empty; while (str != "끝") { str = Console.ReadLine(); foreach (Narrator narrator in narrators) { narrator.Speak(str); } } } } }