본문 바로가기
멀티캠퍼스 풀스택 과정/AI

AI[CLOVA Voice] 텍스트를 음성으로 변환하기

by 이쟝 2022. 4. 7.

https://www.ncloud.com/ 에 접속해 로그인 후(메뉴 > 서비스 > 구현할 서비스 선택 후 이용 신청)

 

이용신청하는 법

 

메뉴 > 서비스 > AI Service CLOVA Voice > 사용가이드 > CLOVA Voice API v1 바로가기(API 가이드로) > 왼쪽 메뉴 탭에서 tts (Premium) > API 예제에서 Java 복사하기

 

2022.04.06 - [멀티캠퍼스 풀스택 과정/AI] - [CFR(Face Recognition)] 얼굴인식 구현하기

지난 포스팅에서 쓰인 home.jsp 사용하기

1. home.jsp에 voice form 연결 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF_8">
<title>home.jsp</title>
</head>
<body>
	<h1>Ai Service API</h1>
	<ol>
		<li><a href="/cfrform">CFRecognition:얼굴감지</a></li>
		<li><a href="/cfrform2">CFR(Celebrity):유명인감지</a></li>
		<li><a href="/voiceform">Voice:텍스트 음성변환</a></li>
	</ol>
</body>
</html>

2. Home에서 voiceform 로 넘어갈 파일 생성 clova_voice.jsp 

스피커 버튼을 누르면 textarea의 데이터를 값고 서버에 갔다가 온다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>clova_voice</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<h1>CLOVA Voice</h1>
<textarea id='text' rows='20' cols='100'></textarea>
<input type='button' value='스피커' id='speakerBtn'/> 
</body>
</html>

Javascript에서 XMLHttpRequest 객체를 이용해서 비동기식으로 구현

XMLHttpRequest 객체
현재 대부분의 주요 웹 브라우저는 서버에 데이터를 요청하기 위한 XMLHttpRequest 객체를 내장하고 있다.
XMLHttpRequest 객체는 서버로부터 XML 데이터를 전송받아 처리하는 데 사용된다.
 
이 객체를 사용하면 웹 페이지가 전부 로딩된 후에도 서버에 데이터를 요청하거나 서버로부터 데이터를 전송해준다. 즉, 웹 페이지 전체를 다시 로딩하지 않고 일부분만을 갱신할 수 있게 된다.

[XMLHttpRequest의 메서드들]
.open(데이터 전송방식, 맵핑주소)
.setRequestHeader(서버로 보내는 데이터에 대한 헤더) 
.send(서버로 보낼 정보(보낼 문자열)) -> 여기서는 textarea안의 text 
.onload(서버에서 받은 데이터(response)를 가지고 함수 실행!)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
	$(function(){
		$("#speakerBtn").click(function(){
			
			// 비동기식 처리를 할 수 있는 객체
			let xhr = new XMLHttpRequest();
			
			// 응답받은 데이터의 데이터타입 설정
			xhr.responseType='blob';
			
			// 서버에 접속하기(open, setReqeustHeader, send)
			xhr.open('post', '/voiceOk');
			xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 
			xhr.send("text="+$("#text").val()); 
            
                        // 서버에서 응답을 받으면(success같은 역할) 실행
			xhr.onload = function(){ // 응답을 받으면 실행할 함수
			    let audioURL = URL.createObjectURL(this.response);
			    let audio = new Audio(); 
			    audio.src = audioURL;
			    audio.play();
			}
		});
	});
</script>
</head>
<body>
<h1>CLOVA Voice</h1>
<textarea id='text' rows='20' cols='100'></textarea>
<input type='button' value='스피커' id='speakerBtn'/>
</body>
</html>

3. 맵핑할 Controller생성하기 

package com.campus.myapp.controller;

@Controller
public class Clova_Voice {

	@GetMapping("voiceform")
	public String voiceHome() {
		return "clova_voice";
	}
	
	@PostMapping("/voiceOk")
	public void voice(String text, HttpServletResponse response) {
    
	}
}
매개변수 text는 textarea에 적은 데이터 클라이언트에서 보낸 데이터(보이스로 바꿀 문자)이다. 

보낸 데이터를 다시 받아야 하기 때문에 response를 매개변수로 해서 받는다. 

[홈페이지에서 복사한 코드를 넣는다. ]

1) 애플리케이션 클라이언트 아이디값과 시크릿값을 붙여넣는다.

package com.campus.myapp.controller;

@Controller
public class Clova_Voice {
	
	@PostMapping("/voiceOk")
	public void voice(String text, HttpServletResponse response) {
        String clientId = "애플리케이션 클라이언트 아이디값";
        String clientSecret = "애플리케이션 클라이언트 시크릿값";
        
        try {
            String text = URLEncoder.encode("만나서 반갑습니다.", "UTF-8"); // 13자
            String apiURL = "https://naveropenapi.apigw.ntruss.com/tts-premium/v1/tts";
            URL url = new URL(apiURL);
            HttpURLConnection con = (HttpURLConnection)url.openConnection();
            con.setRequestMethod("POST");
            con.setRequestProperty("X-NCP-APIGW-API-KEY-ID", clientId);
            con.setRequestProperty("X-NCP-APIGW-API-KEY", clientSecret);
            // post request
            String postParams = "speaker=nara&volume=0&speed=0&pitch=0&format=mp3&text=" + text;
            con.setDoOutput(true);
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
            wr.writeBytes(postParams);
            wr.flush();
            wr.close();
            int responseCode = con.getResponseCode();
            BufferedReader br;
            if(responseCode==200) { // 정상 호출
                InputStream is = con.getInputStream();
                int read = 0;
                byte[] bytes = new byte[1024];
                // 랜덤한 이름으로 mp3 파일 생성
                String tempname = Long.valueOf(new Date().getTime()).toString();
                File f = new File(tempname + ".mp3");
                f.createNewFile();
                OutputStream outputStream = new FileOutputStream(f);
                while ((read =is.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, read);
                }
                is.close();
            } else {  // 오류 발생
                br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
                String inputLine;
                StringBuffer response = new StringBuffer();
                while ((inputLine = br.readLine()) != null) {
                    response.append(inputLine);
                }
                br.close();
                System.out.println(response.toString());
            }
        } catch (Exception e) {
            System.out.println(e);
        }
	}
}

2) 매개변수로 받는 text와 변수가 같기 때문에  text의 String(데이터 타입)을 삭제한다.(매개변수 받은 text로 사용하기 위해서)

package com.campus.myapp.controller;

@Controller
public class Clova_Voice {
	
	@PostMapping("/voiceOk")
	public void voice(String text, HttpServletResponse response) {
        String clientId = "애플리케이션 클라이언트 아이디값";
        String clientSecret = "애플리케이션 클라이언트 시크릿값";
        
        try {
            text = URLEncoder.encode("만나서 반갑습니다.", "UTF-8"); // 13자
            String apiURL = "https://naveropenapi.apigw.ntruss.com/tts-premium/v1/tts";
            URL url = new URL(apiURL);

3) 요청 파라미터를 참고해서 목소리를 바꿀 수 있다. 

 String postParams = "speaker=목소리 이름&volume=0&speed=0&pitch=0&format=mp3&text=" + text;

4) 클라이언트에게 데이터를 넘겨줄 것이기 때문에 FileOutputStream( )이 아니라 response객체의 getOutputStream( )메서드를 사용한다. (정상 호출일 때)

    	        if(responseCode==200) { // 정상 호출
                InputStream is = con.getInputStream();
                int read = 0;
                byte[] bytes = new byte[1024];
                // 랜덤한 이름으로 mp3 파일 생성
                String tempname = Long.valueOf(new Date().getTime()).toString();
                File f = new File(tempname + ".mp3");
                f.createNewFile();
                //OutputStream outputStream = new FileOutputStream(f);
                OutputStream outputStream = response.getOutputStream();
                while ((read =is.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, read);
                }
                is.close();

[전체 코드]

	@PostMapping("/voiceOk")
	@ResponseBody
	public void voice(String text, HttpServletResponse response) { // text는 textarea에서 보낸 데이터(보이스로 바꿀 문자)
		
        String clientId = "yn3cunbe88";//애플리케이션 클라이언트 아이디값";
        String clientSecret = "sbKvQnX9Q5plhD7lYFP4dYRqZFDD4ma18zMp8usj";//애플리케이션 클라이언트 시크릿값";
 
        try {
            text = URLEncoder.encode(text, "UTF-8"); // 13자
            String apiURL = "https://naveropenapi.apigw.ntruss.com/tts-premium/v1/tts";
            URL url = new URL(apiURL);
            HttpURLConnection con = (HttpURLConnection)url.openConnection(); // con에 data가 있음
            con.setRequestMethod("POST");
            con.setRequestProperty("X-NCP-APIGW-API-KEY-ID", clientId);
            con.setRequestProperty("X-NCP-APIGW-API-KEY", clientSecret);
            // post request
            String postParams = "speaker=jinho&volume=0&speed=0&pitch=0&format=mp3&text=" + text;
            con.setDoOutput(true);
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
            wr.writeBytes(postParams);
            wr.flush();
            wr.close();
            int responseCode = con.getResponseCode();
            System.out.println(responseCode);
            BufferedReader br;
            if(responseCode==200) { // 정상 호출
                InputStream is = con.getInputStream();
                int read = 0;
                byte[] bytes = new byte[1024];
                // 랜덤한 이름으로 mp3 파일 생성
                String tempname = Long.valueOf(new Date().getTime()).toString();
                File f = new File(tempname + ".mp3");
                f.createNewFile();
                //OutputStream outputStream = new FileOutputStream(f); 
                OutputStream outputStream = response.getOutputStream();  // response로 다시 클라이언트에게 데이터 넘겨줌
                while ((read =is.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, read);
                }
                is.close();
            } else {  // 오류 발생
                br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
                String inputLine;
                StringBuffer res = new StringBuffer();
                while ((inputLine = br.readLine()) != null) {
                    res.append(inputLine);
                }
                br.close();
                System.out.println(response.toString());
            }
        } catch (Exception e) {
            System.out.println(e);
        }
	}