티스토리 뷰

최근 AI 서비스가 어떤 것들이 있나 알아보면서(내년 사업 계획의 일환)

 

괜찮아 보이는 서비스가 있어서 한번 사용해보고 공유해 보려고 한다.

 

조사하기 앞서 몇 가지 조건이 붙었는데

 

1. 텍스트 기반으로 무언가를 할 수 있어야 한다.

2. AI를 사용한 서비스면 좋다.

3. API를 제공해야 한다. 

 

위 조건을 모두 만족하는 서비스 중에서, 내가 조사한 것 중에 가장 괜찮아보였던 서비스는 D-ID 였다.

https://www.d-id.com/

 

여러가지 서비스를 제공하는데,

 

그 중에서 가장 괜찮아 보이는 기능은 텍스트를 입력하면 그걸 사람 얼굴이 움직이면서 읽어준다는 것이다.

 

내가 사용하려는 기능은 API 키가 필요하기 때문에 회원가입을 해줘야한다.

 

로그인을 눌렀을 때 게스트페이지에서 Settings/API 를 누르면 회원가입을 하라고 나온다.

 

ㅇㅇ

 

회원 가입을 진행하고나서 API Key를 발급 받는다.

 

API Key는 다시 안보여주니 잘 저장해두자. 그리고 credit이 들어온 것도 확인

 

20 크레딧을 준다.

 

테스트 용도로 credit을 아껴써야하는게, 영상 15초당 1credit이기 때문에 많이 못 써본다.

 

Twilio에 비해서 많이 짜다.

 

좌측에 Developer Hub로 진입하면 아래와 같은 페이지로 들어가게 되는데, 필요한건 Talks 부분이다.

 

 

 

여기서부터 작성할 내용은 이 페이지에 자세히 작성되어 있다. 그리고, 친절하게 영상도 다 제공한다.

(Postman만으로도 사용이 가능하다)

 

이제 구현해보자.

 

사전 준비

 

가장 중요한건 API key 지만, 몇 가지 더 필요한 게 있다.

 

반드시 필요한 건 Presenter의 URL 이다.

 

Presenter 사진은 D-ID에서 제공하는 걸 가져다쓰면 된다. 

 

Create Video 첫페이지에서 우 클릭 후 아무거나 하나 구해온다.

 

우 클릭 후 이미지 URL 복사해두자.

https://create-images-results.d-id.com/DefaultPresenters/Emma_f/image.jpeg

 

감정도 넣을 수 있으므로 자기가 쓰고 싶은 감정을 하나 선택한다.

 

 

그리고 한글도 지원한다. TTS를 Microsoft걸 지원하기 때문에, 어떤 목소리를 사용할지 찾아놓자.

https://learn.microsoft.com/ko-kr/azure/ai-services/speech-service/language-support?tabs=tts

 

이제 코드로 넘어간다.

 

구현

단순 외부 연결만을 하는 것이므로 특별한 코드는 없다.

 

Model

요청 객체 하나만 사용했다.

@FeignClient(name = "D-ID Client", url = "https://api.d-id.com", configuration = {DIdRequestHeader.class})
public interface DidFeignClient {
    @PostMapping("/talks")
    Object generateDidTalksVideo(@RequestBody DidVideoGenerateRequestDto didVideoGenerateRequestDto);

    @GetMapping("talks")
    Object getDidTalksVideo(String id);
}

Controller

@RestController
@RequiredArgsConstructor
public class DidController {

    private final DidService didService;

    @PostMapping("/talks")
    public ResponseEntity<Object> generateVideo(@RequestBody Object didVideoGenerateRequestDto) {
        Object resultObject = didService.generateVideo(didVideoGenerateRequestDto);
        return ResponseEntity.ok(resultObject);
    }

    @GetMapping("/talks/{id}")
    public ResponseEntity<Object> getVideo(@PathVariable String id) {
        Object resultObject = didService.getVideo(id);
        return ResponseEntity.ok(resultObject);
    }
}

 

Service

@Service
@RequiredArgsConstructor
public class DidService {
    private final DIDFeignClient didFeignClient;
    
    public Object generateVideo(Object didVideoGenerateRequestDto) {
        return didFeignClient.generateDidTalksVideo(didVideoGenerateRequestDto);
    }

    public Object getVideo(String id) {
        return didFeignClient.getDidTalksVideo(id);
    }
}

Client

@FeignClient(name = "didClient", url = "https://api.d-id.com", configuration = {DIdRequestHeader.class})
public interface DIDFeignClient {
    @PostMapping("/talks")
    Object generateDidTalksVideo(@RequestBody Object didVideoGenerateRequestDto);

    @GetMapping("/talks/{id}")
    Object getDidTalksVideo(@PathVariable String id);
}

 

헤더는 Github에서 확인

 

요청을 날려보자.

 

그럼 아래와 같은 결과가 온다.

 

 

필요한건 id다. id를 복사하고 PathVariable로 전달해줘야한다.

 

 

Get 요청을 날려주면 아래와 같은 긴 응답이 나온다.

{
    "user": {
        "features": [
            "stitch",
            "clips:write",
            null
        ],
        "stripe_plan_group": "deid-trial",
        "authorizer": "basic",
        "owner_id": "google-oauth2|105759186747154018860",
        "id": "google-oauth2|105759186747154018860",
        "plan": "deid-trial",
        "email": "kimdongha15@gmail.com"
    },
    "script": {
        "length": 24,
        "ssml": false,
        "subtitles": false,
        "type": "text",
        "provider": {
            "type": "microsoft",
            "voice_id": "ko-KR-JiMinNeural"
        }
    },
    "metadata": {
        "driver_url": "bank://lively/driver-06/original",
        "mouth_open": false,
        "num_faces": 1,
        "num_frames": 126,
        "processing_fps": 45.60790450139159,
        "resolution": [
            512,
            512
        ],
        "size_kib": 1507.0439453125
    },
    "audio_url": "https://d-id-talks-prod.s3.us-west-2.amazonaws.com/google-oauth2%7C105759186747154018860/tlk_rr22CFTkc7HmT-a0jbQQn/microsoft.wav?AWSAccessKeyId=AKIA5CUMPJBIK65W6FGA&Expires=1700403102&Signature=ZVtibtcrA1jrCaO11HcE21MxTcg%3D&X-Amzn-Trace-Id=Root%3D1-6558c61d-61b4b41471c5c04805bbb832%3BParent%3D40bba0ea7c144189%3BSampled%3D0%3BLineage%3Da08e19fe%3A0",
    "created_at": "2023-11-18T14:11:42.527Z",
    "face": {
        "mask_confidence": -1,
        "detection": [
            224,
            198,
            484,
            553
        ],
        "overlap": "no",
        "size": 512,
        "top_left": [
            98,
            119
        ],
        "face_id": 0,
        "detect_confidence": 0.9998306035995483
    },
    "config": {
        "stitch": false,
        "pad_audio": 0,
        "align_driver": true,
        "sharpen": true,
        "reduce_noise": false,
        "auto_match": true,
        "normalization_factor": 1,
        "show_watermark": true,
        "motion_factor": 1,
        "result_format": ".mp4",
        "fluent": false,
        "align_expand_factor": 0.3
    },
    "source_url": "https://d-id-talks-prod.s3.us-west-2.amazonaws.com/google-oauth2%7C105759186747154018860/tlk_rr22CFTkc7HmT-a0jbQQn/source/image.jpeg?AWSAccessKeyId=AKIA5CUMPJBIK65W6FGA&Expires=1700403102&Signature=piYnFEAJ8gwZV3a7CTB%2FqB1E%2BEo%3D&X-Amzn-Trace-Id=Root%3D1-6558c61d-61b4b41471c5c04805bbb832%3BParent%3D40bba0ea7c144189%3BSampled%3D0%3BLineage%3Da08e19fe%3A0",
    "created_by": "google-oauth2|105759186747154018860",
    "status": "done",
    "driver_url": "bank://lively/",
    "modified_at": "2023-11-18T14:11:46.045Z",
    "user_id": "google-oauth2|105759186747154018860",
    "subtitles": false,
    "id": "tlk_rr22CFTkc7HmT-a0jbQQn",
    "duration": 5.064,
    "started_at": "2023-11-18T14:11:42.571",
    "result_url": "https://d-id-talks-prod.s3.us-west-2.amazonaws.com/google-oauth2%7C105759186747154018860/tlk_rr22CFTkc7HmT-a0jbQQn/1700316702527.mp4?AWSAccessKeyId=AKIA5CUMPJBIK65W6FGA&Expires=1700403106&Signature=tO0lJNYg7StfQkYWP%2B48A2sZm18%3D&X-Amzn-Trace-Id=Root%3D1-6558c622-0792718c4a6c45f9416347d1%3BParent%3De3e219eb4d0c22d8%3BSampled%3D1%3BLineage%3D6b931dd4%3A0"
}

 

마지막 result_url으로 비디오를 다운받을 수 있다.

 

정확히는 모르겠지만 저장기간이 24시간 이라는 것 같다.

 

추가적으로 webhook을 걸어서, 영상 생성이 완료되면 응답을 받는 기능도 있는 것 같지만 여기선 사용하지 않았다.

 

단점

 

솔직히 다양한 서비스를 써보면서 이 서비스만큼 편하고 좋은 서비스를 써본적이 없다.

 

그런데, 단점은 딱 하나다.

 

비싸다.

좋은 서비스 특) 비쌈

 

15초당 크레딧이 하나씩 빠진다. 그런데 가격이 올라도 제공하는 크레딧은 많이 늘어나질 않는다.

 

아래는 15초짜리 영상을 두 번 만든 내 계정의 크레딧이다.

 

15초 짜리를 두 번 사용함

 

Github

https://github.com/imsosleepy/d-id-java.git

 

마치며

간만에 재밌는 서비스를 써봐서 한번 소개해봤다.

 

짧게 끊고 싶었지만, 이리저리 길어져버렸다.

 

이제부터는 github도 조금씩 살려보려고한다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함