[고수도 한 걸음부터] 7전 8기 n8n도전기 7전 8기 n8n도전기 4탄 숏츠 자동화 workflow를 만들어 보아요

소개

안녕하세요! SamAltoran입니다!

지난 토요일 모각과 토요일 - 일요일 님이 추진한 n8n 해커톤에 참여했습니다.
토요일 모각을 참여했을 때, 실은 해커톤까지 참여할지는 미정이 었던 상태였는데요.

모각을 진행하고 n8n을 키고 보다보니 어느새 저도 일원이 되어있었습니다.ㅎㅎ

밤을 새면서 무언가를 해본 게 이렇게 가슴 뛰는 일인가 싶습니다.
열정적인 분들과 같은 시공간에 있어서 행복했습니다.

이왕 해커톤에서 참여하는 것 목표를 정하면 좋을 것 같아서
Youtube Shorts 자동화 workflow를 구축해보는 것을 목표로 했습니다.

Shorts 자동화 Workflow는 이전에 한 번 도전을 했던 workflow였는데요.
제 실력이 부족하여 생각보다 오래걸리는 세팅과 낮은 퀄리티로 우여곡절을 겪었고
그래서 중도 포기했던 Workflow였어서 완성을 해보고 싶었습니다.

이에 시현의 모험이라는 유튜버의 영상을 Reference 삼아 진행을 하였고,
저의 사례의 상당 부분이 해당 영상에서 비롯됩니다.

https://www.youtube.com/watch?v=8nML6B7poHM

그럼 간 밤 동안 제가 진행했던 workflow 앞으로 설명을 드리겠습니다.

먼저 결과부터 보고 가시죠!

https://f002.backblazeb2.com/file/creatomate-c8xg3hsxdu/1fba365f-0cc1-41e5-bf4a-34c359a359c3.mp4

진행 방법

준비물

1. ChatGPT,Gemini,Claude **Chat Model** API (이미지, 음성 생성을 위한 프롬프트제작용)
(Gemini로 진행했습니다.)

2. 기본 프롬프트를 위한 ChatGPT

3. Google Sheet n8n Google Credential 연동)(예시파일공유)

4. 이미지 생성 모델 - fal.ai에서 제공하는 Recraft v3를 사용

5. 동영상 생성 모델 - fal.ai에서 제공하는 Kling 1.6 사용

6. 음성, 사운드 생성 모델 - fal.ai에서 제공하는 elevenlabs turbo2.5(음성), soundeffect(효과음) 사용

7. 영상 편집 프로그램 - [Creatomate](https://creatomate.com/)

동작원리

한국어의 과정을 보여주는 다이어그램

동작원리는 이렇습니다.

기반되는 prompt를 어서 주제, 나레이션, 캡션으로 만듭니다. 이때 만드는 프롬프트가 가장 중심이 되고

숏츠에서 나오는 컨텐츠가 되고, 생성되는 이미지도 기반이되니 가장 중요한 부분이라고 볼 수 있습니다.

Prompt를 가지고, 이미지를 생성, 생성된 이미지를 기반한 영상생성, 장면에 어울리는 효과음 생성 나레이션 음성 생성을 진행하고 생성된 소스파일들을 한 대 모아 조립하여 숏츠가 완성됩니다.

이 동작을 진행하는 n8n을 workflow를 보고 하나하나씩 보겠습니다.

비즈니스 프로세스의 흐름도

원고작성(Prompt)+구글 Sheet

예시 문서

구글 Sheet에서 숏츠 영상의 주제와 이미지, 음성 생성의 기본이 되는 프롬프트를 데이터 베이스화하여 만들었습니다. Reference 영상 기반으로 아래의 프롬프트를 활용하여 만들었구요. 복사 붙어넣기하면 자동으로 칸이 나뉘어져 입력됩니다.

Column 구성은 추후 만들 자동 배포까지 고려하여 제작되었습니다.

너는 Faceless 자동화 유튜브 쇼츠 콘텐츠 기획 전문가야
저작권에 문제가 없는 사람의 운세 이야기, 사주팔자, 50~60대가 좋아하는 오늘의 운세 등을 바탕으로 5가지 주제를 추천해줘
출력 형식:

- 코드 블록(') 안에 탭으로 구분된 텍스트를 제공해줘
- 각 행은 Subject, Narraon, Status, Caption, Publish 순서로 탭(1t)으로 구분
- 헤더 없이, 바로 데이터 행만 5개 제공
지침:
- Subject: 후킹 요소를 넣어 5~7단어 이내로 작성
- Narration: 30초 분량(약 60~70단어)의 나레이션
- Status: 항상 '준비'
- Caption: 10줄 분량의 심층 부연 설명. 줄 바꿈 없이 셀 하나에 들어가도록.
- Publish: 항상 '대기중

아래는 다른 주제지만
약간의 예시를 줄게
>>>
판도라의 상자: 호기심의 대가 그리스 신화 속 판도라는 제우스로부터 절대 열어보지 말라는 상자를 받았습니다.
하지만 호기심을 이기지 못한 그녀가 상자를 열자, 세상의 모든 재앙과 질병이 쏟아져 나왔죠. 
마지막에 남은 것은 오직 '희망'뿐이었습니다. 
이 이야기는 인간의 호기심과 그 결과에 대한 책임, 그리고 어떤 상황에서도 희망은 남아 있다는 메시지를 전합니다. 
준비 팝도라의 상자 이야기는 인류의 고통에 대한 그리스인들의 설명이자, 지식과 호기심이 가져올 수 있는 양면성에 대한 경고입니다. 
제우스는 인간에게 불을 가져다준 프로메테우스에 대한 복수로 판도라와 그녀의 상자를 만들었다고 합니다. 
흥미로운 점은 원래 그리스 신화에서는 '상자'가 아닌 '항아리(피토 스)'였으며, 
'판도라의 상자'라는 표현은 16세기 에라스무스의 오역에서 비롯되었다는 사실입니다. 
오늘날 '판도라 의 상자를 열다'라는 표현은 돌이킬 수 없는 문제를 일으키는 행동을 비유할 때 사용되지만, 
희망이 남아있다는 메 시지도 함께 담고 있습니다. 대기중
>>>

구글 Sheet에 정보를 넣으면 불러들어봐야 겠죠?

Google Sheet 연동이 되었다고 가정을 하고 진행을 하겠습니다.

Document : 파일
Sheet : 시트
Filter를 통해서 status 에서 '준비' 인 것 filter

여기서 option을 넣어서
Retun only first matching row를 합니다.
영상이 만들어지면 Status : 준비 -> 완료 로 자동 변경되고
그 이후 workflow를 다시 실행하면 다음 row가 진행되니 이걸 꼭 해주는 것이 좋습니다.

애드워즈에서 이메일 마케팅 설정의 스크린 샷

Narration 생성

내레이션은 elevenlab로 진행합니다.

이야기 목소리를 만드는 방법을 보여주는 다이어그램

Post -> 만들어질 때까지 Wait -> Get으로 가져옵니다.

Method: POST  
URL: https://queue.fal.run/fal-ai/elevenlabs/tts/turbo-v2.5  

Header 1: Authorization: Bearer YOUR_API_KEY  
Header 2: Content-Type: application/json  

Body:
{
  "text": "{{ $json.Narration }}",
  "language_code": "ko",
  "voice": "elevenlabs에서 찾은 성우이름",
  "speed": 1.1
}

Header Auth로 API 값을 입력하면되는데요.

header 값에 입력하는 방식
Header Auth에 Credential 입력해두는 방식이 있습니다.

Header 방식은 Send Header를 on 하고
Name : Authorization
key : Bearer {YOUR_API_KEY}
이렇게 입력하면 되고

Header Auth에 Credential 만드는 방식은
위의 정보를 미리 입력해두고 저장해두는 방식입니다.
나중에 다른 node에 바로 연결해서 쓸 수 있어서 좋습니다.

<미리 입력해둔 Header Auth>

get node는 아래와 같이 구성하시면 됩니다.

Method: GET  
URL: https://queue.fal.run/fal-ai/elevenlabs/requests/{{ $json.request_id }}  

Header 1: Authorization: Bearer YOUR_API_KEY  (from credential: fal.ai)  
Header 2: Content-Type: application/json  

{{ $json.request_id }}는 구성하시는 node에 따라 바뀔 수 있어요.

Image 생성과 Image 기반 동영상 생성

<영상 생성 전체 노드>

< 프롬프트 >

내래이션을 음성파일을 확보하면 이제 내래이션과 어울리는 장면을 뽑아야 합니다.

장면은 5개 정도로 구성할 예정이구요
5개씩 5초 총 25초를 구성할 예정입니다.

더 많은 장면, 더 긴 쇼츠를 만드려면?
25~30초 구성인 내래이션을 50~55초 정도로 늘리고.
장면을 뽑을 때 10개 정도로 뽑으면 되겠습니다.

장면을 뽑으려면 먼저 장면의 기준이되는 이미지 생성하는 것이 좋습니다.
프롬프트 -> 이미지 생성 -> 영상 생성
이 기준으로 되어야 장면에 맞는 영상이 만들어집니다.

내래이션에 맞도록 장면을 나누기위해 아래의 프롬프트를 사용했습니다.
해당 프롬프트는 Reference 영상인 시현의 모험 채널의 영상을 기준으로 하였습니다.
이 프롬프트를 수정하면 다른 부분으로도 발전이 될 것 같습니다.

주어진 스크립트에 따라 매우 몰입감 있고 영화적인 장면 프롬프트를 5장 생성해 주세요 .
요구사항 :
1. 생생하고 감각적인 동작 중심 묘사를 사용할 것 (예: 움켜잡다, 밀치다, 달 리다, 쓰러지다 등)
2. 스크립트에 따라 논리적인 순서로 전개될 것
3. 평범한 일상보다는 독특하고 극적이며 시각적으로 강렬한 장면 위주로 구성 할 것
4. 몰입감을 높이기 위해 시네마틱 샷 등의 키워드를 포함할 것
5. 각 프롬프트는 200자 이내로 상세하게 작성
6. 큰따옴표("")는 사용하지 않음
7. 프롬프트는 영어로 생성함
예시:
Cinematic low-angle shot of Hercules collapsing to one knee in a rain-soaked temple, his fists trembling as divine energy flickers out, thunder cracking behind shattered marble pillars
스크립트:
{{ $('Get row(s) in sheet').item.json.Narration }}

{{ $('Get row(s) in sheet').item.json.Narration }} 이 부분은 Node 상황에 따라 바뀔 수 있습니다.

해당 프롬프트를 이용해 Basic LLM Chain 노드를 활용해서 LLM에게 전달합니다.
그리고 Basic LLM Chain 노드 내 Require Specific Output Format을 활성화하여
Item List output Parser를 연결하고 5로 값을 설정해 5개의 장면으로 나눕니다.

<이미지, 영상 생성>

위에서 Request로 음성 생성한 것과 동일한 방식으로 이미지, 영상을 생성할 예정입니다.

먼저 이미지 생성부터 진행합니다. 5개로 쪼개진 Output Prompt를 이제 Http Request 노드를 통해서 이미지 생성 모델에게 API로 전달합니다.

Method: POST  
URL: https://queue.fal.run/fal-ai/recraft-v3  

Header 1: Authorization: Bearer YOUR_API_KEY  (from credential: fal.ai)  
Header 2: Content-Type: application/json  

Body:
{
  "prompt": "{{ $json.text }}",
  "image_size": "portrait_16_9",
  "style": "digital_illustration/neon_calm"
}


fal.ai의 recraft-v3 모델을 사용하였습니다.

이 부분에서
영상의 이미지 퀄리티, 원하는 스타일에 설정하실 수 있습니다.

추구하는 영상이나 이미지가 있다면
그것을 구현을 잘하는 이미지 생성 모델로 변경해서 세팅하시면 됩니다.
저는 workflow 구현을 목적으로 Reference 그대로 진행하였습니다.

이미지 생성까지 10초 정도 소요가 되므로 Get node전 Wait 노드로 15초를 대기하고
Get을 합니다.

get노드를 아래 처럼 생성하면 됩니다~!

Method: GET  
URL: https://queue.fal.run/fal-ai/recraft-v3/requests/{{ $json.request_id }}  

Header 1: Authorization: Bearer YOUR_API_KEY  (from credential: fal.ai)  
Header 2: Content-Type: application/json  

Body: 없음

이제 생성된 이미지를 바탕으로 영상을 만듭니다.
마찬가지로 Http Request로 영상모델에게 요청 해야하는데요.
이미지를 기준으로 동영상을 만들기 위해선
input 값으로 앞에서 생성된 Image를 전달하면 되겠죠?

동일하게 API 키 값을 Header에 넣고,
Body 부분에
Prompt : 쪼개져온 장면에 대한 Text
Image_url : 앞에서 생성한 이미지 URL

를 전달합니다.

5개의 Image URL이 있으므로 n8n은 자동으로 5번 request를 보낼 예정입니다.

Method: POST  
URL: https://queue.fal.run/fal-ai/kling-video/v1.6/standard/image-to-video  

Header 1: Authorization: Bearer YOUR_API_KEY  (from credential: fal.ai)  
Header 2: Content-Type: application/json  

Body:
{
  "prompt": "{{ $('Image Prompt').item.json.text }}",
  "image_url": "{{ $json.images[0].url }}",
  "duration": "5",
  "aspect_ratio": "9:16",
  "negative_prompt": "blur, distort, and low quality"
}

요청을 보내면 영상 제작까지 120~150초 정도 시간이 걸립니다.
Get 하기 전 Wait 노드를 이용해 약 200초 정도 넉넉하게 기다립니다.

그 후 Get으로 정보를 가져옵니다.
세팅 값을 아래를 참고하세요~!

Method: GET  
URL: https://queue.fal.run/fal-ai/kling-video/requests/{{ $json.request_id }}  

Header 1: Authorization: Bearer YOUR_API_KEY  (from credential: fal.ai)  
Header 2: Content-Type: application/json  

Body: 없음

자 여기까지 오셨으면

  1. 내래이션 음성 확보

  2. 이미지 기반 영상 확보

이렇게 두 가지 됩니다.

이 두개를 합쳐서 만들어도 되지만.
Shorts를 더 재미있게 만들기 위해 알맞은 효과음을 넣어 보도록 합니다.

효과음 생성

효과음 생성을 위한 프롬프트를 만들기 위해 Basic LLM Chain을 하나 소환 합니다.
앞에 이미지를 생성을 위한 프롬프트 생성 LLM은 Item List output Parser로 5개로 나눴지만
이번엔 그럴 필요가 없습니다. 5개 아이템으로 Input이 들어옵니다. (전 무지성으로 했다가 25개 만들었었죠.)

효과음 생성을 위한 프롬프트 생성 프롬프트는 아래 처럼했어요

##이미지 프롬프트에 어울리는 효과음을 생성해주세요.
#요구사항:
1. 결과물은 영어로 5-10 단어로 간결하게 생성할 것
2. 큰따옴표("")는 사용하지 않음
3. 사람의 목소리가 생성될 가능성이 있는 프롬프트가 나와서는 안 됨
4. 프롬프트는 영어로 생성함
5. Only Plain Text
예시:
A howling desert wind sweeping across the dunes
이미지 프롬프트:
{{ $('Image Prompt').item.json.text }}

그 다음 Elevenlabs에 전달하여 효과음을 생성을 요청합니다.

세팅은 이전과 거의 같은데
이번엔 효과음을 생성하는 모델이 따로 있어 그 URL에 요청합니다.

Method: POST  
URL: https://queue.fal.run/fal-ai/elevenlabs/sound-effects  

Header 1: Authorization: Bearer YOUR_API_KEY  (from credential: fal.ai)  
Header 2: Content-Type: application/json  

Body:
{
  "text": "{{ $json.text }}",
  "duration_seconds": 5
}

요청 후 마찬가지로 15초 대기 후에 Get하도록 합니다.

Merge 후 영상 편집 요청

이제 거의 다왔습니다. 지금까지 모은 소스를 확인해보면

  1. 내래이션

  2. 5초짜리 영상 5개

  3. 5초짜리 효과음 5개

이 3가지 재료를 가지고 영상 편집을 APi를 통해 Creatomate에 보냅니다.

?? Creatomate?

Creatomate는 이미 쓰신 분들도 계시고
처음 보신 분도 계시겠는데.
간단하게 웹상에서 영상 편집을 할 수 있는 도구입니다.

영상 템플릿을 Json형태로 저장하고, 입출력이 가능해서
API를 보내면 해당 변수에 맞춰서 가지고 있는 소스를 버무려 영상을 빚을 수 있습니다.

제가 글 윗 부분에 Shorts Workflow를 만들다 실패했다. 라고 말씀드렸는데요
딱 이 부분에서 실패를 했습니다.

소스가 영상의 재료라면
위의 템플릿은 영상을 완성하는 쉐프라고 보면 될 거 같습니다.

원하는 영상이 만들어지려면
템플릿을 자유롭게 다루고 그에 맞도록 소스를 넣어서
양산해버리면 되는데요.

이 부분은 이번 Workflow를 다시 따라하면서도 아쉬운 부분이고
더 퀄리티업을 위해 디벨롭이 필요한 부분이라고 생각합니다.

디자인 AI가 발전되고 있고... Json 형태로 템플릿이 가능하니
이 부분을 인지해서 AI를 통해 디자인 하는 것도 좋긴하겠네요.

저는 개인적으로 Dynamic Subtitle을 실현하고 싶었는데...
좀 더 찾아봐야 할 거 같습니다.

다시 Meage & Request to Creatomate

갑자기 실패한 생각이 나서 딴길로 샜네요..
어두육미하고 지금까지 뽑은 소스를 Merge해서 보내는 부분을 보겠습니다.

Merge는 간단합니다.

  1. 내래이션

  2. 5초짜리 영상 5개

  3. 5초짜리 효과음 5개

Merge mode는 Append(추가), Number of inputs는 3개니까 3을 입력합니다.


그 다음 Aggregate는 통해 하나의 item으로 묶었습니다.
reference 영상에서도 해당 부분은 해도되고 안해도 된다고 하셨는데.
저는 이 부분은 그냥 따라했습니다.

Put Output in Field에서 기본값이 Data인데요.
저는 해당 영상과 동일하게 지웠습니다.
안 지워도 되는 것이긴한데 Data라고 할당하는 변수가 많으니 지우는 것도 좋은 것같습니다.

그리고 1tem으로 모았지만 쓸데없는 변수값이 많아 Set node를 통해 변수를 재정의했습니다.

{
"scene1": "{{ $json[''][1].video.url }}",
"scene2": "{{ $json[''][2].video.url }}",
"scene3": "{{ $json[''][3].video.url }}",
"scene4": "{{ $json[''][4].video.url }}",
"scene5": "{{ $json[''][5].video.url }}",
"sound1": "{{ $json[''][6].audio.url }}",
"sound2": "{{ $json[''][7].audio.url }}",
"sound3": "{{ $json[''][8].audio.url }}",
"sound4": "{{ $json[''][9].audio.url }}",
"sound5": "{{ $json[''][10].audio.url }}",
"narration": "{{ $json[''][0].audio.url }}"
}

이렇게 이전 변수를 간단하게 재정의 했습니다.

자 이제 모든 소스가 준비되었구요. Creatomate에 Request를 날리면 됩니다.
그전에 Request를 날리면 받아주는 Creatomate가 준비가 되어있어야합니다.
위에서 살짝 언급했던 대로

소스를 적절하게 나눠 배치해주는 템플릿이 있어야 한다는 거죠.
그리고 그 템플릿은 Json형태로 저장이 되구요.
해당 영상에서도 Json 을 공유하는데
저도 거의 비슷하게 구현을 해봤습니다.

< Creatomate Templete 설정>

Creatomate에 대한 자세한 설명은 생략하고 바로 템플릿부터 말씀을 드리겠습니다.
저희가 이미지를 9:16으로 제작하였고, 동영상도 이에맞도록 생성을 하였으니
템플릿도 이에 맞도록 생성을 해줘야합니다.

New를 눌러 해당 이미지 크기나 비율에 맞는 기본 템플릿을 생성하구요

생성된 템플릿을 클릭해서 들어가면 우측 상단에 { } 라고 Code node같은 아이콘이 보입니다.
해당 템플릿을 Json으로 보여주는 기능이구요.

거기에 아랫 Json을 복사하여 붙이시면 제가 사용했던 템플릿을 고스란히 사용할 수 있습니다.
(Ref. 영상과 기본틀이 완전히 동일하니 미세조정이나 문구 조정은 필요합니다.)

{
  "output_format": "mp4",
  "width": 1080,
  "height": 1920,
  "frame_rate": "30 fps",
  "snapshot_time": 3.5,
  "fonts": [
    {
      "family": "Pretendard",
      "weight": 700,
      "style": "normal",
      "source": "9f3bf16d-9b5a-4a02-89cc-e3ab08a2d053"
    }
  ],
  "elements": [
    {
      "id": "b7a7fa0f-913d-4618-8f9b-544e4a10e023",
      "name": "Narration",
      "type": "audio",
      "track": 1,
      "time": 0,
      "duration": null,
      "audio_fade_out": 0,
      "dynamic": true
    },
    {
      "id": "82f45c55-41fa-4941-9e6c-b231e74d3cbe",
      "name": "Composition-1",
      "type": "composition",
      "track": 2,
      "duration": 5,
      "elements": [
        {
          "id": "069ab77c-c712-4dcb-97c1-e53742c5028b",
          "name": "Sound-Effect-1",
          "type": "audio",
          "track": 1,
          "time": 0,
          "volume": "30%",
          "dynamic": true
        },
        {
          "id": "ec97a518-7e6f-4eb0-9239-bf0851e6cdac",
          "name": "Video-1",
          "type": "video",
          "track": 3,
          "time": 0,
          "duration": null,
          "source": "c74e6e61-6af3-40c0-8187-679d94bca81a",
          "volume": "120%",
          "dynamic": true,
          "animations": [
            {
              "easing": "linear",
              "type": "scale",
              "fade": false,
              "track": 0,
              "end_scale": "120%",
              "start_scale": "100%"
            }
          ]
        }
      ]
    },
    {
      "id": "cc65ccda-17a1-46bf-acf2-2e236c821ff9",
      "name": "Composition-2",
      "type": "composition",
      "track": 2,
      "duration": 5,
      "elements": [
        {
          "id": "83aeb067-75b4-4d11-a919-f0e31caf44ea",
          "name": "Sound-Effect-2",
          "type": "audio",
          "track": 1,
          "time": 0,
          "volume": "30%",
          "dynamic": true
        },
        {
          "id": "ea5981b3-7f49-4223-94e6-73dd6f525e94",
          "name": "Video-2",
          "type": "video",
          "track": 2,
          "time": 0,
          "duration": null,
          "source": "c74e6e61-6af3-40c0-8187-679d94bca81a",
          "volume": "120%",
          "dynamic": true,
          "animations": [
            {
              "easing": "linear",
              "type": "scale",
              "fade": false,
              "track": 0,
              "end_scale": "120%",
              "start_scale": "100%"
            }
          ]
        }
      ]
    },
    {
      "id": "6e3c3c92-e225-4b13-876c-e9718850d97e",
      "name": "Composition-3",
      "type": "composition",
      "track": 2,
      "duration": 5,
      "elements": [
        {
          "id": "ce038f7a-2f5a-4824-862c-5960462707df",
          "name": "Sound-Effect-3",
          "type": "audio",
          "track": 1,
          "time": 0,
          "volume": "50%",
          "dynamic": true
        },
        {
          "id": "33015222-ea54-4acd-a546-a07ac2276af2",
          "name": "Video-3",
          "type": "video",
          "track": 3,
          "time": 0,
          "duration": null,
          "source": "c74e6e61-6af3-40c0-8187-679d94bca81a",
          "volume": "120%",
          "dynamic": true,
          "animations": [
            {
              "easing": "linear",
              "type": "scale",
              "fade": false,
              "track": 0,
              "end_scale": "120%",
              "start_scale": "100%"
            }
          ]
        }
      ]
    },
    {
      "id": "7e0bef98-064e-4605-bef3-6311b1ef5f7f",
      "name": "Composition-4",
      "type": "composition",
      "track": 2,
      "duration": 5,
      "elements": [
        {
          "id": "2ebff79c-d0f0-40da-91b6-5f64417db485",
          "name": "Sound-Effect-4",
          "type": "audio",
          "track": 1,
          "time": 0,
          "volume": "50%",
          "dynamic": true
        },
        {
          "id": "502bd66c-e86b-417d-b658-590c5df0bf7a",
          "name": "Video-4",
          "type": "video",
          "track": 3,
          "time": 0,
          "duration": null,
          "source": "c74e6e61-6af3-40c0-8187-679d94bca81a",
          "volume": "120%",
          "dynamic": true,
          "animations": [
            {
              "easing": "linear",
              "type": "scale",
              "fade": false,
              "track": 0,
              "end_scale": "120%",
              "start_scale": "100%"
            }
          ]
        }
      ]
    },
    {
      "id": "b0ebfcb1-86f3-4eff-987a-251e2504d679",
      "name": "Composition-5",
      "type": "composition",
      "track": 2,
      "duration": 5,
      "animations": [
        {
          "time": "end",
          "duration": 1.724,
          "easing": "quadratic-out",
          "reversed": true,
          "type": "fade"
        }
      ],
      "elements": [
        {
          "id": "e13aa87e-d000-43d0-9140-526b8a7b9074",
          "name": "Sound-Effect-5",
          "type": "audio",
          "track": 1,
          "time": 0,
          "volume": "50%",
          "dynamic": true
        },
        {
          "id": "2d395d87-c92d-4609-86b5-e9693ebc14a8",
          "name": "Video-5",
          "type": "video",
          "track": 3,
          "time": 0,
          "duration": null,
          "source": "c74e6e61-6af3-40c0-8187-679d94bca81a",
          "volume": "120%",
          "dynamic": true,
          "animations": [
            {
              "easing": "linear",
              "type": "scale",
              "fade": false,
              "track": 0,
              "end_scale": "120%",
              "start_scale": "100%"
            }
          ]
        }
      ]
    },
    {
      "id": "3a993a11-02c0-4cb4-9878-f4647ae1ab54",
      "name": "Outro",
      "type": "text",
      "track": 4,
      "time": 25.0127,
      "duration": 4.9998,
      "width": "82%",
      "height": "35%",
      "x_alignment": "50%",
      "y_alignment": "50%",
      "text": "자세한 이야기는 n캡션에 적어두었어요.",
      "font_family": "Open Sans",
      "font_weight": "700",
      "font_size": "5.6 vmin",
      "fill_color": "#ffffff"
    }
  ]
}

! 여기서 부터 영상편집 핵심 !

템플릿이 완성되었다 가정하면
이제 이 템플릿에 우리가 Request를 보내야합니다.

이 템플릿이 받을 수 있도록 해야합니다. Creatomate에는 템플릿마다 아이디가 있는데
그것을 지정해줘야합니다.

Creatomate API는 별도로 받았다는 가정하에 진행하면

Creatomate 템플릿 우측 상단의 Use Template 버튼을 누르고

API Integration을 클릭하면

해당 템플릿의 cURL을 복사할 수 있습니다.
복사한 cURL을 가지고 Http Reqest node에 있는 Import cURL을 이용해

붙여넣기하면 끝!

Request를 날리고 렌더링이 될때 까지 60초 정도 기다립니다.

그리고 google sheet에 업데이트하면 끝입니다. 고생하셨습니다.

결과와 배운점

해봐야지 해봐야지 하면서 workflow 구현을 계속 미뤄왔었는데.
해커톤 참여를 통해 하나의 사례를 만든 것 같습니다.
해커톤 참여중 12시쯤 귀가본능 발휘로 막차시간 검색하고 있었는데
한 번 해보자 한 제 자신에게 먼저 칭찬 한 박수보냅니다
옆에서 같이 열정 주신 스터디원들에게 감사 드립니다!

지난 번과 다르게 이번엔 나의 스타일을 안넣고 빠르게 workflow구현부터 진행했습니다.
동작하는 걸 보다보니 계속 다른 아이디어가 떠오르더라구요.

현재 workflow를 통해 생성된 이미지는 제 스타일이 아닙니다.
어디서 미세조정을 하고, 어딜 마사지 해야겠다는 아이디어가 생각이 들고요.

필요해서 곧 할거 같긴한데. 생성된 이미지가 아닌 Ref. image를 찾고
스토리 있는 프롬프트를 통한 숏츠제작을 진행하면 더 퀄리티가 높아질 거란 생각이 듭니다.

배운점1


위의 workflow..
비쌉니다.

제가 5달러 OpenAI API에 해놓고 지금 3달 동안 쓰는 API 자린고비인데요.
어제 워크플로우 진행하면서 테스트하는데 13달러를 썼습니다.

ㅎㅎㅎ

정말 궁금해서 요금을 정리해봤는데요.

탕후루 하나씩 사라집니다.
퀄리티가 높다면 괜찮겠지만..
아니라면 고민이 되는 금액이긴합니다.

배운점2

세 가지 핵심을 배웠습니다.

  1. 생성 프롬프트를 잘 짜야한다.
    내래이션이 영상 길이를 조절한다. 원하는 길이보다 짧거나 길 수 있는데.
    완전 자동화를 위해선 이 부분을 어떻게 조절할지 숙제를 풀어야한다.

  2. 이미지가 스타일을 고정한다.
    이미지 기반 동영상 생성 방식이면
    계속 이 부분이 들어갈 것이다.
    만약 내가 하나의 캐릭터를 고정한다면?
    캐릭터를 고정된 이미지로 활용해서 Image to Image로 다른 장면을 생성(고정된 캐릭터)
    그 기반으로 만들면 될 듯하다.

  3. 최신 모델을 기다리자.
    잦은 시행착오는 지갑이 얇아진다..ㅠㅠ

도움 받은 글 (옵션)

유튜버 시현의 모험, 시현님의 Reference 영상을 참고했습니다.

https://www.youtube.com/watch?v=8nML6B7poHM

5
3개의 답글

뉴스레터 무료 구독

👉 이 게시글도 읽어보세요