Node.js로 몇 분 만에 1,000개의 개인화된 동영상 생성

비디오는 고객과 소통할 수 있는 강력한 방법입니다. 최근 데이터에 따르면 비디오는 대부분의 브랜드에서 가장 참여도가 높은 디지털 콘텐츠입니다. 그러나 비디오 생성은 지루할 수 있습니다. 특히 보낼 사용자가 수천 명인 경우.

다행스럽게도 코딩을 할 수 있을 때 그렇게 할 필요는 없습니다. 이 자습서에서는 사용자의 이름과 세부 정보를 추가하는 1,000개의 개인화된 생일 축하 비디오를 자동화하는 방법과 코드를 사용하여 비디오 편집을 자동화하는 방법을 보여줍니다.

전제 조건



Node.js



JavaScript에 대한 경험이 있다고 가정합니다. Node.js를 통해 바닐라 JavaScript를 사용하여 응용 프로그램을 빌드하지만 원하는 것을 자유롭게 사용하십시오.

샷스택 API 키



Shotstack.io은 비디오 데이터를 설명하기 위해 JSON을 사용하는 REST 아키텍처를 사용하는 비디오 편집 API입니다. API는 복잡한 비디오 편집 기능을 지원합니다. free account을 생성하여 API 키를 가져옵니다. shotstack.io/doc/guide에서 전체 문서 및 API 참조를 참조하십시오.

영상 선택



이 자습서에서는 가상의 고객에게 생일 할인을 제공하는 표준 프로모션 비디오를 사용합니다. 이 비디오는 코드로 완전히 생성되었지만 After Effects와 같은 비디오 편집 솔루션에 내장된 사전 렌더링된 비디오를 사용하여 동일한 결과를 얻을 수 있습니다.



동영상 콘텐츠 중 일부를 삭제하고 빈 공간을 맞춤 데이터로 사용합니다. 이 데이터는 JSON 파일에 배치되며 누락된 모든 항목을 새 값과 애니메이션으로 다시 배치합니다.

이 특정 템플릿의 경우 이름, 연령, 더 어린 "가짜"연령, 할인 코드 및 할인 금액을 개인화합니다.

Shotstack은 편집 가능한 타임라인처럼 작동하는 JSON 객체를 사용합니다. 이는 데스크탑 비디오 편집 솔루션이 작동하는 방식과 유사한 방식으로 작동하며, 비디오 지속 시간을 나타내는 타임라인과 콘텐츠를 조작할 수 있는 개별 클립이 있습니다.

이 기사에서는 이 비디오가 어떻게 만들어졌는지에 대해서는 다루지 않겠지만 이 특정 비디오가 어떻게 편집되었는지 이해하고 싶다면 JSON 템플릿을 자세히 살펴볼 수 있습니다. 정말 관심이 있다면 이 튜토리얼은 이러한 비디오를 직접 디자인하는 방법에 대해 좀 더 자세히 설명합니다.

이 예에서는 애니메이션이 미리 렌더링된 단순화된 템플릿을 사용하여 개인화된 콘텐츠가 있어야 하는 특정 HTML 자산을 쉽게 추가할 수 있습니다.

{
  "timeline": {
    "fonts": [
      {
        "src": "https://shotstack-assets.s3-ap-southeast-2.amazonaws.com/fonts/FiraCode-Regular.ttf"
      },
      {
        "src": "https://shotstack-assets.s3-ap-southeast-2.amazonaws.com/fonts/Nexa-Bold.otf"
      }
    ],
    "background": "#000000",
    "tracks": [
      {
        "clips": [
          {
            "asset": {
              "type": "html",
              "html": "<p>firstName</p>",
              "css": "p { font-family: \"Nexa Bold\"; font-size: 128px; color: #ffffff; text-align: left; }"
            },
            "start": 2.35,
            "length": 1.45,
            "offset": {
              "y": -0.23,
              "x": 0.05
            },
            "transition": {
              "out": "carouselDown"
            }
          },
          {
            "asset": {
              "type": "html",
              "html": "<p><b>age</b></p>",
              "css": "p { font-family: \"Nexa Bold\"; font-size: 149px; color: white; text-align: left; }"
            },
            "position": "center",
            "start": 5.2,
            "length": 1.3,
            "offset": {
              "y": -0.23,
              "x": 0.05
            },
            "transition": {
              "in": "zoom",
              "out": "zoom"
            }
          },
          {
            "asset": {
              "type": "html",
              "html": "<p><b>fakeAge</b></p>",
              "css": "p { font-family: \"Nexa Bold\"; font-size: 384px; color: #ffffff; text-align: left;}"
            },
            "position": "center",
            "start": 11.15,
            "length": 2.5,
            "offset": {
              "y": -0.05,
              "x": 0.05
            },
            "transition": {
              "out": "carouselLeft"
            }
          },
          {
            "asset": {
              "type": "html",
              "html": "<p>discountCode</p>",
              "css": "p { font-family: \"Fira Coda\"; font-size: 42px; color: #3498db; text-align: center; background-color: #ffffff; padding: 32px; line-height: 106px; }",
              "width": 320,
              "height": 107
            },
            "start": 17.2,
            "length": 4.8,
            "offset": {
              "y": -0.05,
              "x": 0
            }
          },
          {
            "asset": {
              "type": "html",
              "html": "<p>For discount Off</p>",
              "css": "p { font-family: \"Nexa Bold\"; font-size: 58px; color: #3498db; text-align: left;} span { color: #e74c3c; }"
            },
            "start": 19.2,
            "length": 1.2,
            "offset": {
              "y": -0.302,
              "x": 0.04
            }
          },
          {
            "asset": {
              "type": "html",
              "html": "<p>For <span>discount Off</span></p>",
              "css": "p { font-family: \"Nexa Bold\"; font-size: 58px; color: #3498db; text-align: left;} span { color: #e74c3c; }"
            },
            "start": 20.3,
            "length": 1.7,
            "offset": {
              "y": -0.302,
              "x": 0.04
            }
          }
        ]
      },
      {
        "clips": [
          {
            "asset": {
              "type": "video",
              "src": "https://shotstack-content.s3-ap-southeast-2.amazonaws.com/birthday/birthday-template.mp4",
              "volume": 1
            },
            "start": 0,
            "length": 22
          }
        ]
      }
    ]
  },
  "output": {
    "format": "mp4",
    "resolution": "sd"
  }
}

스프레드시트를 사용한 대량 자동 편집



고객을 위해 우리는 약 1,000명의 조작된 사용자에 대한 정보가 포함된 데이터 세트를 사용할 것입니다. 여기에는 이름, 나이, 가짜 나이, 할인 코드 및 할인 금액이 포함됩니다. 그런 다음 이 CSV의 데이터를 사용하여 JSON 템플릿을 채우고 API로 보냅니다. 전체 스프레드시트는 GitHub에서 찾을 수 있습니다.

CSV 데이터에서 동영상 만들기



지금 해야 할 일은 CSV 파일을 반복하고, 개인화된 데이터 포인트를 JSON 템플릿에 추가하고, 렌더링을 위해 각 비디오 편집 내용을 API로 보내는 것입니다.

아래 스크립트는 Shotstack API 키 세부 정보가 포함된 .env 환경 파일을 사용하여 작동합니다. 내 .env 파일을 살펴보고 스크립트에서 환경 변수를 사용하는 방법을 확인할 수 있습니다.

require("dotenv").config();

const fs = require("fs");
const axios = require("axios").default;
const csv = require("fast-csv");
const argv = require("yargs").argv;
const numWords = require("num-words");
const getAge = require("get-age");
const capitalize = require("capitalize");
const Throttle = require("throttle-stream");

const USER_LIST = "./user-list-test.csv";
const VIDEO_LIST = "./video-list.csv";
const API_KEY = process.env.SHOTSTACK_KEY;
const ENDPOINT = process.env.SHOTSTACK_ENDPOINT;
const CUSTOMER_ID = process.env.SHOTSTACK_CUSTOMER_ID;
const PREVIEW_URL = process.env.SHOTSTACK_PREVIEW_URL;
const TEMPLATE = fs.readFileSync("./template.json", "utf8");
const fileStream = fs.createWriteStream(VIDEO_LIST, { flags: "a" });

let count = 0;

fs.createReadStream(USER_LIST)
  .pipe(new Throttle({ bytes: 200, interval: 1000 }))
  .pipe(csv.parse())
  .on("data", (row) => {
    let age = getAge(row[1]);
    let ageInWords = capitalize.words(numWords(age));

    var mapObj = {
      firstName: row[0],
      age: ageInWords,
      fakeAge: row[2],
      discountCode: row[3],
      discount: row[4],
    };

    let template = JSON.parse(
      JSON.stringify(TEMPLATE).replace(
        /firstName|age|fakeAge|discountCode|discount/gi,
        function (matched) {
          return mapObj[matched];
        }
      )
    );

    axios({
      method: "post",
      url: ENDPOINT,
      headers: {
        "x-api-key": API_KEY,
        "content-type": "application/json",
      },
      data: template,
    }).then(
      (response) => {
        if (response.status !== 201) {
          console.log(row[0], response.data.response.id);
          return;
        }

        let video = response.data.response.id + ".mp4";
        fileStream.write(`${row[0]},${PREVIEW_URL}${CUSTOMER_ID}/${video}\n`);
        console.log("Video queued for: " + row[0]);
      },
      (error) => {
        throw error;
      }
    );
  });

그 결과 몇 분 안에 1000개의 개인화된 비디오가 렌더링되었습니다.



스크립트를 실행하면 수천 개의 개인화된 템플릿이 렌더링을 위해 API로 전송되는 것을 볼 수 있으며 모든 출력 데이터는 video-list.csv라는 CSV 파일에 저장되며 여기에는 각 개별 동영상의 URL이 포함됩니다. 게시물용 이미지

shotstack.io


구축할 준비가 되셨습니까?



비디오는 이 디지털 세상에서 커뮤니케이션을 증폭시키는 데 중요한 역할을 해왔습니다. 의심의 여지가 없습니다. 다음으로 중요한 것은 자동화된 개인화 비디오가 될 것입니다. 개인화된 마케팅 비디오는 마케팅에서 전환율과 참여율이 더 높은 비디오의 미래임이 이미 입증되었습니다. 이 움직임을 활용하기 위해 무엇을 구축하고 있습니까?

다양한 사용 사례에 대한 다양한 템플릿을 시작하려면 Templates 페이지를 방문하십시오.

좋은 웹페이지 즐겨찾기