API/NAVER CLOVA
음성 인식 : CLOVA Speech Recognition (CSR) / CLOVA Voice - Premium
olli2
2022. 1. 26. 00:12
CLOVA Speech Recognition (CSR) : 음성 인식
- 사람의 목소리를 텍스트로 변환 | 음성을 텍스트로 변환 : STT(Speech-To-Text)
- 언어 선택 가능
- Application에서 CLOVA Speech Recognition (CSR) 서비스 추가하여 사용
개발 가이드 확인
[ STT ]
https://api.ncloud-docs.com/docs/ai-naver-clovaspeechrecognition-stt
stt (Speech-To-Text) - CLOVA Speech Recognition(CSR)
api.ncloud-docs.com
[ TTS ]
https://api.ncloud-docs.com/docs/ai-naver-clovavoice-ttspremium
tts (Premium) - CLOVA Voice
api.ncloud-docs.com
CLOVA Speech Recognition (CSR) : 음성 인식 실습
(1) 결과를 콘솔에 출력
(2) 파일 업로드 / 추출된 텍스트 출력
(3) 언어 선택 <select name=”language”> 추가
index.jsp
<a href="clovaSTTForm">Speech To Text</a><br><br>
<a href="clovaSTTForm2">Speech To Text2 : 언어 선택 추가</a><br><br>
<a href="clovaTTSForm">Text To Speech</a><br><br>
STTService
package com.ai.ex.service;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import org.json.JSONObject;
import org.springframework.stereotype.Service;
@Service
public class STTService {
public String clovaSpeechToText(String filePathName) {
String clientId = ""; // Application Client ID";
String clientSecret = ""; // Application Client Secret";
String result = "";
try {
String imgFile = filePathName;
File voiceFile = new File(imgFile);
String language = "Kor"; // 언어 코드 ( Kor, Jpn, Eng, Chn )
String apiURL = "https://naveropenapi.apigw.ntruss.com/recog/v1/stt?lang=" + language;
URL url = new URL(apiURL);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setUseCaches(false);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Content-Type", "application/octet-stream");
conn.setRequestProperty("X-NCP-APIGW-API-KEY-ID", clientId);
conn.setRequestProperty("X-NCP-APIGW-API-KEY", clientSecret);
OutputStream outputStream = conn.getOutputStream();
FileInputStream inputStream = new FileInputStream(voiceFile);
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
BufferedReader br = null;
int responseCode = conn.getResponseCode();
if(responseCode == 200) { // 정상 호출
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} else { // 오류 발생
System.out.println("error!!!!!!! responseCode= " + responseCode);
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
}
String inputLine;
if(br != null) {
StringBuffer response = new StringBuffer();
while ((inputLine = br.readLine()) != null) {
response.append(inputLine);
}
br.close();
System.out.println(response.toString());
result = jsonToString(response.toString()); // JSON 문자열에서 텍스트 추출
resultToFileSave(result); //파일로 저장
} else {
System.out.println("error !!!");
}
} catch (Exception e) {
System.out.println(e);
}
return result;
}
public String clovaSpeechToText2(String filePathName, String language) {
String clientId = ""; // Application Client ID";
String clientSecret = ""; // Application Client Secret";
String result = "";
try {
String imgFile = filePathName;
File voiceFile = new File(imgFile);
//String language = "Kor"; // 언어 코드 ( Kor, Jpn, Eng, Chn )
String apiURL = "https://naveropenapi.apigw.ntruss.com/recog/v1/stt?lang=" + language;
URL url = new URL(apiURL);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setUseCaches(false);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Content-Type", "application/octet-stream");
conn.setRequestProperty("X-NCP-APIGW-API-KEY-ID", clientId);
conn.setRequestProperty("X-NCP-APIGW-API-KEY", clientSecret);
OutputStream outputStream = conn.getOutputStream();
FileInputStream inputStream = new FileInputStream(voiceFile);
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
BufferedReader br = null;
int responseCode = conn.getResponseCode();
if(responseCode == 200) { // 정상 호출
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} else { // 오류 발생
System.out.println("error!!!!!!! responseCode= " + responseCode);
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
}
String inputLine;
if(br != null) {
StringBuffer response = new StringBuffer();
while ((inputLine = br.readLine()) != null) {
response.append(inputLine);
}
br.close();
System.out.println(response.toString());
result = jsonToString(response.toString()); // JSON 문자열에서 텍스트 추출
resultToFileSave(result); //파일로 저장
} else {
System.out.println("error !!!");
}
} catch (Exception e) {
System.out.println(e);
}
return result;
}
// API 서버로부터 받은 JSON 형태의 결과 데이터를 전달받아서 text 추출
public String jsonToString(String jsonResultStr) {
String resultText = "";
try {
//org.json.JSONObject; 사용한 경우
JSONObject jsonObj = new JSONObject(jsonResultStr);
resultText = (String) jsonObj.getString("text");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return resultText;
}
// 음성 파일에서 추출한 텍스트를 txt 파일로 저장
public void resultToFileSave(String result) {
try {
String fileName = Long.valueOf(new Date().getTime()).toString();
String filePathName = "C:/upload/" + "stt_" + fileName + ".txt";
FileWriter fw = new FileWriter(filePathName);
fw.write(result);
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
APIController
@Autowired
private STTService sttService;
@Autowired
private TTSService ttsService;
// Speech-To-Text
@RequestMapping("/clovaSTTForm")
public String clovaSTTForm() {
return "sttView";
}
// 언어 선택 추가
// Speech-To-Text
@RequestMapping("/clovaSTTForm2")
public String clovaSTTForm2() {
return "sttView2";
}
// TTS : 텍스트를 음성 파일로 변환
// (1) 결과를 upload 폴더에 mp3 파일로 저장
/*@RequestMapping("/clovaTTS")
public void clovaTTS() {
ttsService.clovaTextToSpeech();
}*/
@RequestMapping("/clovaTTSForm")
public String clovaTTSForm() {
return "ttsView";
}
sttView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>STT</title>
<script src="<c:url value='/js/jquery-3.6.0.min.js'/>"></script>
<script src="<c:url value='/js/stt.js'/>"></script>
</head>
<body>
<!-- 파일 업로드 -->
<h3>CSR : STT (음성을 텍스트로 변환)</h3>
<form id="sttForm" enctype="multipart/form-data">
파일 : <input type="file" id="uploadFile" name="uploadFile">
<input type="submit" value="결과 확인">
</form>
<br><br>
<!-- 결과 출력 -->
<h3>STT : 음성을 텍스트로 변환한 결과</h3>
<div id="resultDiv"></div><br><br>
<div><audio preload="auto" controls></audio></div>
<br><br>
<a href="/">index 페이지로 이동</a>
</body>
</html>
stt.js
/**
* stt.js
*/
$(function(){
$('#sttForm').on('submit', function(event){
event.preventDefault();
var formData = new FormData($('#sttForm')[0]);
// 업로드된 파일명 알아오기
var fileName = $('#uploadFile').val().split("\\").pop();
// alert($('#uploadFile').val());
$('audio').prop("src", '/voice/' + fileName);
$.ajax({
url:"clovaSTT",
enctype:'multipart/form-data',
type:"post",
data:formData,
processData: false, // 필수
contentType: false, // 필스
success:function(result){
$('#resultDiv').text(result);
},
error:function(e){
alert("오류가 발생했습니다." + e)
}
});
});
});
sst2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>STT2</title>
<script src="<c:url value='/js/jquery-3.6.0.min.js'/>"></script>
<script src="<c:url value='/js/stt2.js'/>"></script>
</head>
<body>
<!-- 파일 업로드 -->
<h3>CSR : STT (음성을 텍스트로 변환)</h3>
<form id="sttForm" enctype="multipart/form-data">
파일 : <input type="file" id="uploadFile" name="uploadFile"><br><br>
언어 : <select name="language">
<option value="Kor">한국어</option>
<option value="Eng">영어</option>
<option value="Jpn">일본어</option>
<option value="Chn">중국어</option>
</select><br><br>
<input type="submit" value="결과 확인">
</form>
<br><br>
<!-- 결과 출력 -->
<h3>STT : 음성을 텍스트로 변환한 결과</h3>
<div id="resultDiv"></div><br><br>
<div><audio preload="auto" controls></audio></div>
<br><br>
<a href="/">index 페이지로 이동</a>
</body>
</html>
sst2.js
/**
* stt2.js
*/
$(function(){
$('#sttForm').on('submit', function(event){
event.preventDefault();
var formData = new FormData($('#sttForm')[0]);
// 업로드된 파일명 알아오기
var fileName = $('#uploadFile').val().split("\\").pop();
// alert($('#uploadFile').val());
$('audio').prop("src", '/voice/' + fileName);
$.ajax({
url:"clovaSTT2",
enctype:'multipart/form-data',
type:"post",
data:formData,
processData: false, // 필수
contentType: false, // 필스
success:function(result){
$('#resultDiv').text(result);
},
error:function(e){
alert("오류가 발생했습니다." + e)
}
});
});
});
APIRestController
@Autowired
private TTSService ttsService;
@RequestMapping("/clovaSTT")
public String clovaSTT(@RequestParam("uploadFile") MultipartFile file) {
String result = "";
try {
// 1. 파일 저장 경로 설정 : 실제 서비스되는 위치 (프로젝트 외부에 저장)
String uploadPath = "C:/upload/";
// 2. 원본 파일 이름 알아오기
String originalFileName = file.getOriginalFilename();
String filePathName = uploadPath + originalFileName;
// 3. 파일 생성
File file1 = new File(filePathName);
// 4. 서버로 전송
file.transferTo(file1);
// 서비스에 파일 path와 파일명 전달 -> 서비스 메소드에서 변경
// 서비스에서 반환된 PoseVO 리스트 저장
result = sttService.clovaSpeechToText(filePathName);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
// language 언어 선택 추가
@RequestMapping("/clovaSTT2")
public String clovaSTT2(@RequestParam("uploadFile") MultipartFile file,
@RequestParam("language") String language) {
String result = "";
try {
// 1. 파일 저장 경로 설정 : 실제 서비스되는 위치 (프로젝트 외부에 저장)
String uploadPath = "C:/upload/";
// 2. 원본 파일 이름 알아오기
String originalFileName = file.getOriginalFilename();
String filePathName = uploadPath + originalFileName;
// 3. 파일 생성
File file1 = new File(filePathName);
// 4. 서버로 전송
file.transferTo(file1);
// 서비스에 파일 path와 파일명 전달 -> 서비스 메소드에서 변경
// 서비스에서 반환된 PoseVO 리스트 저장
result = sttService.clovaSpeechToText2(filePathName, language);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
CLOVA Voice - Premium : 음성 합성 API 서비스
- 텍스트를 음성으로 변환 : TTS(Text-To-Speech)
- 텍스트 파일을 입력 받아서 변환된 음성 파일(mp3/wav) 반환
- 언어, 음색 선택 가능
- CLOVA Voice - Premium 서비스 추가하여 사용
CLOVA Voice - Premium 실습
(1) 문자열 전송하고 결과를 mp3파일로 저장
(2) 파일 업로드 / 결과 mp3파일 <audio> 플레이
TTSService
package com.ai.ex.service;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;
import org.springframework.stereotype.Service;
@Service
public class TTSService {
public void clovaTextToSpeech() {
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=clara&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");
File f = new File("C:/upload/" + tempname + ".mp3"); // C:/upload/에 랜덤한 이름으로 저장
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);
}
}
// 파일 경로 및 언어를 전달 받아
// 저장된 파일명(voiceFileName) 반환
public String clovaTextToSpeech2(String filePathName, String language) {
String clientId = "86au6kn68u";//애플리케이션 클라이언트 아이디값";
String clientSecret = "HFv2tMkPNhrTzOsxXJ5eGdteQfkWJC90UMnsQXeA";//애플리케이션 클라이언트 시크릿값";
String voiceFileName = "";
try {
// 전달 받은 파일에서 텍스트를 추출하기 위한 fileRead() 함수 사용
// 함수에게 전달하고 텍스트 받음
String fileContents = fileRead(filePathName);
// "만나서 반갑습니다." 라는 글자를 '인코딩해서' 전달
String text = URLEncoder.encode(fileContents, "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=" + language + "&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");
voiceFileName = "tts_" + tempname + ".mp3"; // 음성 파일 이름
File f = new File("C:/upload/" + voiceFileName); // C:/upload/에 랜덤한 이름으로 저장
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);
}
return voiceFileName; // 저장된 음성 파일명 반환
}
// 파일 경로를 전달받아서, 파일 내 텍스트 추출해서 반환하는 함수
public String fileRead(String filePathName) {
String result = "";
try {
File file = new File(filePathName);
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String line = "";
while((line = br.readLine()) != null){
result += line;
}
br.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(result); // 출력해서 확인
return result; // 저장된 음성 파일명 반환
}
}
ttsView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TTS</title>
<script src="<c:url value='/js/jquery-3.6.0.min.js'/>"></script>
<script src="<c:url value='/js/tts.js'/>"></script>
</head>
<body>
<!-- 파일 업로드 -->
<h3>TTS : 텍스트를 음성으로 변환</h3>
<form id="ttsForm" enctype="multipart/form-data">
파일 : <input type="file" id="uploadFile" name="uploadFile"><br><br>
언어 : <select name="language">
<option value="nara">한국어, 여성</option>
<option value="jinho">한국어, 남성</option>
<option value="nhajun">한국어, 아동(남)</option>
<option value="ndain">한국어, 아동(여)</option>
<option value="clara">영어, 여성</option>
<option value="matt">영어, 남성</option>
<option value="shinji">일본어, 남성</option>
<option value="carmen">스페인어, 여성</option>
<option value="meimei">중국어, 여성</option>
</select><br><br>
<input type="submit" value="결과 확인">
</form>
<br><br>
<!-- 결과 출력 -->
<h3>TTS : 텍스트를 음성으로 반환한 결과</h3>
<div id="resultDiv"></div><br><br>
<div><audio preload="auto" controls></audio></div>
<br><br>
<a href="/">index 페이지로 이동</a>
</body>
</html>
tts.js
/**
* tts.js
*/
$(function(){
$('#ttsForm').on('submit', function(event){
event.preventDefault();
var formData = new FormData($('#ttsForm')[0]);
// 업로드된 파일명 알아오기 (텍스트파일)
var fileName = $('#uploadFile').val().split("\\").pop();
// alert($('#uploadFile').val());
$.ajax({
url:"clovaTTS",
enctype:'multipart/form-data',
type:"post",
data:formData,
processData: false, // 필수
contentType: false, // 필수
success:function(result){
$('audio').prop("src", '/voice/' + result);
$('#resultDiv').text(result); // 저장된 '음성 파일명' 출력
},
error:function(e){
alert("오류가 발생했습니다." + e)
}
});
});
});
APIRestController
@Autowired
private STTService sttService;
// language 언어 선택 추가
@RequestMapping("/clovaTTS")
public String clovaTTS(@RequestParam("uploadFile") MultipartFile file,
@RequestParam("language") String language) {
String result = "";
try {
// 1. 파일 저장 경로 설정 : 실제 서비스되는 위치 (프로젝트 외부에 저장)
String uploadPath = "C:/upload/";
// 2. 원본 파일 이름 알아오기
String originalFileName = file.getOriginalFilename();
String filePathName = uploadPath + originalFileName;
// 3. 파일 생성
File file1 = new File(filePathName);
// 4. 서버로 전송
file.transferTo(file1);
// 서비스에 파일 path와 파일명 전달 -> 서비스 메소드에서 변경
// 서비스에서 저장된 파일명(result) 받아오기
result = ttsService.clovaTextToSpeech2(filePathName, language);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}