AWS

[ AWS ] - aws polly 음성 전환 후 s3에 저장하기

algml0703 2022. 6. 14. 08:09
반응형
polly

aws에서 제공하는 TTS 서비스로 사용한 만큼만 비용이 부과된다.

* TTS ( Text To Speech )
딥러닝 기술을 이용하여 문자를 음성으로 전환하여 주는 기술이다.

요약

1. aws 로그인 후 aws polly와 s3에 대한 모든 권한을 허용해주는 iam 계정을 생성하고, accessKey와 secretKey를 보관하여 둔다.

2. node.js 환경 기본적인 서버 환경을 구축하여 준다.

3. aws-sdk를 사용하여 s3 버킷을 새롭게 생성하여 준다.

// aws-sdk를 이용하여 개발하기 위해 iam 계정 생성으로 받은 accessKey와 secretKey가 필요하다.

4. aws polly로 텍스트를 음성 전환한다.

5. 전환된 파일을 생성한 버킷에 업로드 한다.

6. 업로드 된 파일을 다시 다운로드해서 확인한다.

 

1. aws 로그인 후 aws polly와 s3에 대한 모든 권한을 허용해주는 iam 계정을 생성하고, accessKey와 secretKey를 보관하여 둔다.

aws에 들어가서 루트 사용자로 로그인 한다.

보안자격증명에 들어간다.  or 콘솔에 iam을 입력 후 들어간다.

왼쪽 대시보드에서 사용자 클릭 후 해당 화면에서 사용자 추가를 클릭한다.

사용자 이름을 설정해주고 다음: 권한을 클릭한다.

엑세스 유형을 선택하는데 다는 편하게 이용하려고 두개 다 선택했다.  보통 aws-sdk 등을 활용하여 cli 로 aws를 사용하는 경우 엑세스 키 - 프로그래밍 방식을 선택하고, 사이트에서 화면을 통해 aws를 조작하는 경우 암호-aws관리 콘솔 엑섹스를 사용한다.

  • 엑세스 키 - 프로그래밍 방식 엑세스의 경우 aws-sdk 사용을 위해 필요한 accesskey와 secretkey를 생성하여 준다.
  • 암호 - aws 관리 콘솔 엑세스의 경우 aws 사이트 접속하여 콘솔 로그인시 로그인을 위한 콘솔 url, 비밀번호 등을 제공하여 준다.

기존 정책 직접 연결을 선택하고 검색 창에 polly 입력하여 AmazonPollyFullAccess를 선택한다. 같은 방식으로 s3를 입력하고 AmazonS3FullAccess를 선택하고 다음:태그를 클릭한다.

태그 추가의 경우 별다른 설정 없이 바로 다음: 검토를 클릭한다.

내용 확인하구 사용자 만들기를 클릭한다.

사용자 추가를 통해 생성된 정보를 보관하여 둔다. 파란색으로 링크된 콘솔 정보도 잘 복사하여 둔다. 해당 링크 누르면 바로 이동되므로 아래에 있는 정보들을 보관하기 전에 이동하지 않도록 주의한다. 해당 정보는 루트 계정으로 이동하면 볼 수는 있으나, 엑세스키의 경우 다시 볼 수 없고 재발급 받아야 하므로 번거로워진다. 

2. node.js 환경 기본적인 서버 환경을 구축하여 준다.

기본적으로 비쥬얼스튜디오코드, node.js 사용 환경 등은 다 세팅되었음을 가정한다.

> mkdir polly-study

우선은 작업용 폴더를 생성한다. 

* mkdir 새로운 폴더를 생성하여 주는 명령어이다.

> cd polly-study
> npm init -y

해당 폴더로 이동한 후 npm init -y을 통해 작업 환경을 생성한다.

* cd 현재 위치를 기준으로 위치 이동하여주는 명령어이다.

* npm init -y는 기본적으로 프로젝트 환경을 생성하여 주는 명령어라고 생각하면 된다.

해당 위치에서 polly.js 파일을 만들어준다.

현재 폴더 구조는 위와 같다.

package.json 파일에 "scripts"부분에 "start":"node polly.js"를 추가하여 준다.

3. aws-sdk를 사용하여 s3 버킷을 새롭게 생성하여 준다.

코드 작성 전에 우선 aws에 접근하기 위해 aws-sdk모듈을 추가하여 준다.

> npm install aws-sdk
import AWS from 'aws-sdk';

const accessKeyId = '';
const secretAccessKey ='';

const s3 = new AWS.S3({
    accessKeyId: accessKeyId,
    secretAccessKey: secretAccessKey
});

// 버킷 생성
const params = {
    Bucket: 'polly-bucket-mihee',
    CreateBucketConfiguration:{
        LocationConstraint: 'ap-northeast-2'
    }
};

s3.createBucket(params, (err, data) => {
    if(err) console.log('err', err);
    console.log('Bucket creaed SuccessFully', data.Location)
});

위의 코드에서 accessKeyId와 secretAccessKey에는 각각 아까 iam을 통해 생성한 엑세스 키와 비밀엑세스키를 넣어준다.

* 주의할 점
params에서 Bucket은 생성되는 버킷의 이름을 설정하는 건데 기존에 존재하는 것과 겹치면 안 되기 때문에 겹치지 않을 만한 이름으로 생성한다.

CreateBucketConfiguration의 LocationConstraint에는 어느 지역의 인스턴스를 사용할 것인지 설정하는 것인데 ap-northeast-2는 서울 지역이다.

위와 같이 설정해둔후 npm run start 명령어를 통해 해당 polly.js파일을 실행 시 버킷이 제대로 생성되면 아래와 같이 나온게 된다.


Error 

npm run start 했을 때

위와 같이 import AWS from 'aws-sdk';
^^^^^^

SyntaxError: Cannot use import statement outside a module 의 에러가 나는 경우에는 package.json파일을 아래와 같이 설정하여 준다  맨 아래 부분에 "type":"module"을 추가한다.


aws사이트 들어가서 콘솔 로그인해서 s3 버킷이 제대로 생성되었는지 확인한다.

iam 사용자 추가해서 받은 콘솔 url로 들어가서 

사용자 이름 : [ 사용자 추가시 설정한 이름] 
암호 : [ 비밀번호 ] 
// 엑세스키와 엑세스 시크릿키가 아니라 사용자 이름과 콘솔 비밀번호이다.

로그인하면 비밀번호 변경하라는 화면이 나올 수도 있는데 나오면 비밀번호 변경 해주면 된다. 그러고 다시 오른쪽 위편에 콘솔 로그인을 누르면 로그인 된다.

로그인 완료 후 콘솔에 s3를 입력 후 들어간다.

내가 생성한 s3 버킷이 존재하는 것을 확인할 수 있다.

4. aws polly로 텍스트를 음성 전환한다.

s3 인스턴스를 생성한 위치 아래에 polly 인스턴스를 생성하여 준다. 기존에 버킷 생성하였던 코드는 주석처리한다.

import AWS from 'aws-sdk';
import fs from 'fs'

const accessKeyId = '';
const secretAccessKey ='';

const s3 = new AWS.S3({
    accessKeyId: accessKeyId,
    secretAccessKey: secretAccessKey
});

const polly = new AWS.Polly({
    accessKeyId: accessKeyId,
    secretAccessKey: secretAccessKey,
    signatureVersion: 'v4',
    region: 'ap-northeast-2'
});

const params = {
//     Bucket: 'polly-bucket-mihee',
//     CreateBucketConfiguration:{
//         LocationConstraint: 'ap-northeast-2'
//     }
// };

// s3.createBucket(params, (err, data) => {
//     if(err) console.log('err', err);
//     console.log('Bucket creaed SuccessFully', data.Location)
// });

// 텍스트를 음성으로 변환시켜주는 함수
export const save_audio_from_text = (
    text
) => {
    const params = {
        'Text': text,
        'OutputFormat': 'mp3',
        'VoiceId':'Seoyeon'
    };
    polly.synthesizeSpeech(params, (err, data) => {
        if(err) {
            throw err
        };
        if( data.AudioStream instanceof Buffer) {
            // 음성 데이터를 s3에 업로드 하는 코드 작성할 곳
            fs.writeFile('./test.mp3', data.AudioStream, (err)=>{
                if(err){
                    throw err
                };
                console.log('the file was saved')
            });
        }
    })
};

save_audio_from_text('안녕하세요');

// 위에 fs도 추가해서 음성 전화이 제대로 되었는지 확인하여 준다.

npm run start로 위의 코드 실행하면 test.mp3로 음성 파일이 생성된다. 

5. 전환된 파일을 이전에 생성한 버킷에 업로드 한다.

// put_object라는 함수로 만들어 사용하였다. put_object 함수를 if (data.AudioStream instanceof Buffer) {}의 안에 넣어준다.

//params 설정
Bucket: [ 생성한 버킷명 ]
Key: [ 업로드되는 파일명 ]
// Key를 기존에 존재하는 것과 같이 하면 기존 파일이 덮어씌워지므로 겹치지 않도록 주의해야 한다.
Body: [ 업로드 될 데이터 ]
ContentType : [ 업로드되는 데이터의 타입]
ACL : [ 해당 파일에 접근성 설정]
// ACL을 설정하지 않으면 파일이 생성되기는 해도 해당 파일이 접근할 수 없게 된다.
export const put_object = async (
    data
) => {
    try{
        const params = {
            Bucket: 'polly-bucket-mihee',
            Key: 'polly-1',
            Body: data.AudioStream,
            ContentType: 'audio/mpeg',
            ACL:'public-read'
        };
        return new Promise((resolve, reject)=>{
            s3.putObject(params, (err) => {
                if(err) throw err;
                return resolve;
            })
        })
    }catch(e){
        console.log(e)
    }
}

여기 까지 전체 코드

import AWS from 'aws-sdk';
import fs from 'fs';

const accessKeyId = '';
const secretAccessKey ='';

const s3 = new AWS.S3({
    accessKeyId: accessKeyId,
    secretAccessKey: secretAccessKey
});

const polly = new AWS.Polly({
    accessKeyId: accessKeyId,
    secretAccessKey: secretAccessKey,
    signatureVersion: 'v4',
    region: 'ap-northeast-2'
});

// 버킷 생성
// const params = {
//     Bucket: 'polly-bucket-mihee',
//     CreateBucketConfiguration:{
//         LocationConstraint: 'ap-northeast-2'
//     }
// };

// s3.createBucket(params, (err, data) => {
//     if(err) console.log('err', err);
//     console.log('Bucket creaed SuccessFully', data.Location)
// });

export const save_audio_from_text = (
    text
) => {
    const params = {
        'Text': text,
        'OutputFormat': 'mp3',
        'VoiceId':'Seoyeon'
    };
    polly.synthesizeSpeech(params, (err, data) => {
        if(err) {
            throw err
        };
        if( data.AudioStream instanceof Buffer) {
            // 음성 데이터를 s3에 업로드 하는 코드 작성할 곳
            put_object(data)
        }
    })
};

export const put_object = async (
    data
) => {
    try{
        const params = {
            Bucket: 'polly-bucket-mihee',
            Key: 'polly-1',
            Body: data.AudioStream,
            ContentType: 'audio/mpeg',
            ACL:'public-read'
        };
        return new Promise((resolve, reject)=>{
            s3.putObject(params, (err) => {
                if(err) throw err;
                return resolve;
            })
        })
    }catch(e){
        console.log(e)
    }
}

save_audio_from_text('안녕하세요 반갑습니다.');

6. 업로드 된 파일을 다시 다운로드해서 확인한다.

// 업로드 된 파일 다운로드
const get_file = () => {
    const params = {
        Bucket: 'polly-bucket-mihee',
        Key:'polly-1'
    };
    s3.getObject(params, (err, data)=>{
        if(err) throw err;
        console.log(data.body)
        fs.writeFileSync('polly.mp3', data.Body)
    })
};

//save_audio_from_text('안녕하세요 반갑습니다.');
get_file()

npm run start로 파일 실행하면 polly.mp3 파일이 생성된다.

 


중요 추가 중요

보안을 위해 accessKey와 secretKey env 파일로 보관하기,

해당 파일을 github에 업로드시 해커나 나쁜 심보를 가진 사람이 해당 정보를 불법적으로 이용해서 많은 비용이 유발될 수 있으므로 반드시 env 파일로 따로 뺀 후 env파일은 업로드되지 않게끔 하는게 좋다.

.env 파일 생성해서 본인의 엑세스 키와 시크릿 키 저장

dotenv 추가

> npm i dotenv

polly.js 파일에 dotenv 관련 코드 추가

import dotenv from 'dotenv';
dotenv.config();

const accessKeyId = process.env.accessKeyId;
const secretAccessKey = process.env.secretAccessKey;

 

전체 코드

import AWS from 'aws-sdk';
import fs from 'fs';
import dotenv from 'dotenv';
dotenv.config();

const accessKeyId = process.env.accessKeyId;
const secretAccessKey = process.env.secretAccessKey;

const s3 = new AWS.S3({
    accessKeyId: accessKeyId,
    secretAccessKey: secretAccessKey
});

const polly = new AWS.Polly({
    accessKeyId: accessKeyId,
    secretAccessKey: secretAccessKey,
    signatureVersion: 'v4',
    region: 'ap-northeast-2'
});

// 버킷 생성
// const params = {
//     Bucket: 'polly-bucket-mihee',
//     CreateBucketConfiguration:{
//         LocationConstraint: 'ap-northeast-2'
//     }
// };

// s3.createBucket(params, (err, data) => {
//     if(err) console.log('err', err);
//     console.log('Bucket creaed SuccessFully', data.Location)
// });

export const save_audio_from_text = (
    text
) => {
    const params = {
        'Text': text,
        'OutputFormat': 'mp3',
        'VoiceId':'Seoyeon'
    };
    polly.synthesizeSpeech(params, (err, data) => {
        if(err) {
            throw err
        };
        if( data.AudioStream instanceof Buffer) {
            // 음성 데이터를 s3에 업로드 하는 코드 작성할 곳
            put_object(data)
        }
    })
};

export const put_object = async (
    data
) => {
    try{
        const params = {
            Bucket: 'polly-bucket-mihee',
            Key: 'polly-1',
            Body: data.AudioStream,
            ContentType: 'audio/mpeg',
            ACL:'public-read'
        };
        return new Promise((resolve, reject)=>{
            s3.putObject(params, (err) => {
                if(err) throw err;
                return resolve;
            })
        })
    }catch(e){
        console.log(e)
    }
};

// s3 업로드 한 파일 다운로드
const get_file = () => {
    const params = {
        Bucket: 'polly-bucket-mihee',
        Key:'polly-1'
    };
    s3.getObject(params, (err, data)=>{
        if(err) throw err;
        console.log(data.body)
        fs.writeFileSync('polly.mp3', data.Body)
    })
};

//save_audio_from_text('안녕하세요 반갑습니다.');
get_file()

 

 

출처

https://yuddomack.tistory.com/entry/Nodejs%EB%A1%9C-AWS-Pollytext-to-speech-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

https://techbless.github.io/2020/03/24/env%EC%99%80-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98%EB%A5%BC-config%ED%8C%8C%EC%9D%BC%EB%B3%B4%EB%8B%A4-%EC%84%A0%ED%98%B8%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0%EC%99%80-undefined-%ED%95%B4%EA%B2%B0%EB%B2%95/

반응형