파트너십

Twelve Labs와 Roe AI로 한층 더 강력해진 비디오 검색을 경험해 보세요

제임스 러, 매니쉬 마헤슈와리

개발자는 Twelve Labs의 Embed API와 Roe AI의 SQL 기반 플랫폼을 통합하여 시맨틱 비디오 검색 애플리케이션을 구축할 수 있습니다. Marengo 2.6 비디오 임베딩 모델을 사용해 업로드된 비디오를 인덱싱하고, Roe AI의 검색 인프라를 통해 자연어로 검색 쿼리를 실행할 수 있습니다.

개발자는 Twelve Labs의 Embed API와 Roe AI의 SQL 기반 플랫폼을 통합하여 시맨틱 비디오 검색 애플리케이션을 구축할 수 있습니다. Marengo 2.6 비디오 임베딩 모델을 사용해 업로드된 비디오를 인덱싱하고, Roe AI의 검색 인프라를 통해 자연어로 검색 쿼리를 실행할 수 있습니다.

In this article

No headings found on page

뉴스레터 구독하기

뉴스레터 구독하기

영상 이해 분야의 최신 기술 업데이트, 튜토리얼 및 인사이트를 받아보세요.

영상 이해 분야의 최신 기술 업데이트, 튜토리얼 및 인사이트를 받아보세요.

AI로 영상을 검색하고, 분석하고, 탐색하세요.

2024. 9. 30.

10분

링크 복사하기

요약: 이 튜토리얼은 Twelve Labs의 Embed API를 Roe AI 플랫폼과 통합하여 강력한 시맨틱 비디오 검색 솔루션을 만드는 방법을 보여줍니다. 가이드를 따라가며 개발자는 최첨단 비디오 임베딩을 기반으로 정확하고 컨텍스트를 이해하는 비디오 검색 시스템을 빠르게 구축할 수 있습니다. 이 튜토리얼을 위해 함께 협업해 준 Roe AI 팀(Sam LiangRichard Meng)에 감사의 말씀을 전합니다.

소개

이 튜토리얼은 Twelve Labs의 Embed APIRoe AI의 SQL 기반 AI 플랫폼과 통합하여 개발자에게 더 고도화된 비디오 이해 도구를 제공하는 데 집중합니다. 이번 통합은 Twelve Labs의 비디오 임베딩 모델과 Roe AI의 데이터 관리 및 검색 기능을 결합하여 정교한 비디오 검색 솔루션을 구축할 수 있게 도와줍니다.

개발자는 이 통합을 활용해 비디오 데이터 내 여러 모달리티 전반에서 컨텍스트, 콘텐츠, 뉘앙스를 이해하는 애플리케이션을 빌드하는 방법을 배우게 됩니다. 또한 복잡한 비디오 데이터를 다루는 과정을 단순화하고, 비디오 검색 기능의 정확도와 효율성을 어떻게 극대화할 수 있는지 탐구합니다. 콘텐츠 플랫폼, 비디오 분석 도구 또는 비디오 데이터를 다루는 어떠한 프로젝트를 개발 중이든, 실제 프로젝트에 이러한 기술을 적용할 수 있는 유용한 인사이트를 얻을 수 있습니다.

1단계: app.roe-ai.com에서 API 토큰 발급받기

Roe AI를 시작하려면 요청을 인증하는 데 필요한 API 토큰을 발급받아야 합니다. 아래 단계에 따라 API 토큰을 확인하세요.

  1. 가입 및 로그인: app.roe-ai.com에 접속하여 새 계정을 만들거나 기존 계정으로 로그인합니다.

  2. API 설정 이동: 로그인 후 API 설정 또는 계정 설정 페이지로 이동하여 API 토큰을 생성하거나 확인할 수 있는 메뉴를 찾습니다.

  3. API 토큰 복사: 생성된 토큰을 클립보드에 복사합니다. 이 토큰은 API 요청 시 계속 사용되므로 안전하게 보관하세요.

  4. 코드에 토큰 적용: 아래 코드 스니펫을 사용하여 API 요청을 위한 헤더를 설정합니다. <Your API Token> 부분을 복사한 실제 토큰으로 대체하세요.

import requests
import json

headers = {
  'Authorization': 'Bearer <Your API Token>'
}

base_api_url = "https://api.roe-ai.com/v1"

이제 토큰 확인이 완료되었으므로, 다음 단계에서 Roe AI API를 사용할 준비가 끝났습니다.

2단계: 비디오 저장을 위한 Roe 데이터 세트 생성

비디오 파일을 Roe AI에 저장하려면 먼저 데이터 세트를 만들어야 합니다. 아래 단계에 따라 새 데이터 세트를 생성하세요.

  1. 데이터 세트 이름 지정: 나중에 쉽게 알아볼 수 있도록 데이터 세트 이름을 지정합니다. 이 가이드에서는 "My Video Dataset"을 사용하며, 원하시는 이름으로 자유롭게 변경하셔도 좋습니다.

  2. API 요청 설정: 아래 코드 스니펫을 사용하여 데이터 세트를 생성합니다. 1단계에서 준비한 헤더와 base API URL이 적용되었는지 확인하세요.

create_dataset_url = f"{base_api_url}/datasets/"

dataset_name = "My Video Dataset"  # Replace with your dataset name

form_data = {
    "name": dataset_name
}

response = requests.post(create_dataset_url, headers=headers, data=form_data)

if response.status_code == 201:
    print("Success")
else:
    print("Failure!")

dataset_id = response.json().get("id") if response.status_code == 201 else None

print(f"Dataset ID: {dataset_id}")
  1. 코드 실행: 준비된 파이썬(Python) 환경에서 코드 스니펫을 실행합니다.

  2. 응답 확인: 데이터 세트가 성공적으로 생성되면 콘솔에 "Success"와 함께 Dataset ID가 출력됩니다. 실패할 경우 "Failure!"가 출력되며 Dataset ID는 None이 됩니다.

  3. 트러블슈팅: 만약 문제가 발생한다면 API 토큰이 올바른지, Roe AI에서 데이터 세트를 생성할 수 있는 권한이 있는지 확인하세요.

데이터 세트가 성공적으로 만들어졌다면 다음 단계인 비디오 파일 업로드로 넘어갑니다.

‍3단계: 생성된 Roe 데이터 세트에 비디오 파일 업로드

데이터 세트 준비를 마쳤으니 이제 비디오 파일을 업로드할 차례입니다. 아래 단계에 따라 비디오를 업로드해 보세요.

  1. 비디오 파일 준비: 업로드할 비디오 파일들이 잘 준비되었는지 확인합니다. 이 예제에서는 "/path/to/video1.mp4" 경로에 "video1.mp4" 파일이 존재한다고 가정합니다.

  2. API 요청 설정: 아래 코드 스니펫을 활용해 비디오 파일을 데이터 세트에 업로드합니다. 이전 단계에서 확인한 Dataset ID를 미리 준비해 두어야 합니다.

upload_files_url = f"{base_api_url}/datasets/files/upload/"

payload = {
    'dataset_id': f"{dataset_id}",
}

# REQUIRED: Add all your VIDEO FILES HERE
files = [
    ('file', ('video1.mp4', open('/path/to/video1.mp4', 'rb'), 'video/mp4')),
    # Add more files as needed
]

response = requests.request("POST", upload_files_url, headers=headers, data=payload, files=files)

if response.status_code == 200:
    print("Success")
else:
    print("Failure!")
  1. 파일 상세 정보 수정: 'video1.mp4' 부분을 실제 비디오 파일명으로 변경하고, '/path/to/video1.mp4' 경로를 로컬 컴퓨터의 실제 경로로 수정합니다. 여러 비디오를 한 번에 업로드하려면 files 리스트에 요소를 추가하면 됩니다.

  2. 코드 실행: 실행 환경에서 해당 파이썬 코드를 구동합니다.

  3. 응답 확인: 업로드가 성공하면 콘솔에 "Success"가 찍힙니다. 에러가 발생한 경우 "Failure!"가 표시됩니다.

  4. 트러블슈팅: 문제가 있다면 API 토큰 유효성, Dataset ID가 일치하는지, 해당 데이터 세트에 파일을 추가할 권한이 활성화되어 있는지 점검하세요.

비디오 파일이 정상적으로 업로드되었다면, 다음 단계에서 데이터 세트를 기반으로 한 테이블을 생성해 보겠습니다.

‍4단계: Roe 데이터 세트에서 테이블 생성

업로드한 비디오 파일들을 기반으로 테이블을 빌드할 차례입니다. 이 테이블은 시맨틱 비디오 검색 서비스의 동작 구조적 뼈대가 됩니다. 다음 단계를 활용하세요.

  1. 테이블 이름 정하기: 직관적으로 식별할 수 있는 테이블 이름을 입력합니다. 여기서는 "my_video_table"을 사용합니다. 이름 지정 시 하이픈(``)은 포함하지 않도록 주의하세요.

  2. API 요청 설정: 아래 코드를 사용해 업로드한 데이터 세트 경로에서 테이블 생성을 호출합니다. 이전 단계의 Dataset ID가 바르게 적용되어 있어야 합니다.

create_table_url = f"{base_api_url}/database/table/import/roe-dataset/"

table_name = "my_video_table"  # Replace with your desired table name

form_data = {
    "table_name": table_name,
    "dataset_id": f"{dataset_id}",
    "sync_dataset": "false",  # Set to "true" if you want to sync the dataset with the table
}

response = requests.post(create_table_url, headers=headers, data=form_data)

if response.status_code == 200:
    print("Success")
else:
    print("Failure!")
  1. 데이터 세트 동기화 옵션: sync_dataset 파라미터는 테이블 데이터를 실시간으로 데이터 세트 현황과 매칭시킬지 결정하는 플래그입니다. "true" 변경 시 원본 데이터 세트 변동 사항이 테이블 데이터에도 지속 반영됩니다. 편의상 이 튜토리얼은 "false"로 유지합니다.

  2. 코드 실행: 파이썬 상에서 코드를 동작시킵니다.

  3. 응답 확인: 테이블 구성이 완료되면 화면에 "Success"가 출력되고 실패 시 "Failure!"가 나타납니다.

  4. 트러블슈팅: 호출에 차질이 발생한다면 토큰 정보, Dataset ID, 계정의 테이블 생성 권한 등을 다시 한번 면밀히 체크하세요.

결과가 문제없다면 데이터 구조를 탐색하기 위해 컬럼을 확인해 볼 수 있습니다.

‍5단계: 사용 가능한 데이터 확인을 위해 테이블 컬럼 조회

테이블 내 속성들을 명확히 설계하고 검색 인덱스를 정밀 조준하기 위해서, 테이블에 어떤 컬럼이 포함되어 있는지 확인해야 합니다. 아래 단계를 시도하세요.

  1. API 요청 설정: 생성된 대상 테이블에서 컬럼을 가져오도록 아래 코드를 세ッティング합니다. 이전 단계의 정확한 테이블 이름이 매겨져야 타겟 컬럼 정보를 파악하기 원활합니다.

table_cols_url = f"{base_api_url}/database/table/{table_name}/columns"

response = requests.get(table_cols_url, headers=headers)

if response.status_code == 200:
    columns = response.json()  # Parsing the JSON response
    print("Success")
    print("Columns:", columns)
else:
    print("Failure! Status Code:", response.status_code)
  1. 코드 실행: 개발 창에서 파이썬 코드를 동작시킵니다.

  2. 응답 확인: 확인이 성공하면 "Success"와 함께 테이블 컬럼 데이터의 구조 목록이 출력됩니다. 실패하는 경우에는 현재 발생한 Status Code가 명시된 에러 로그 메시지가 출력됩니다.

  3. 트러블슈팅: 비정상 동작을 막으려면 다음 지표를 살펴보세요.

    • 사용하고 계신 API 토큰의 권한 만료 여부 및 인증 통과 여부를 검토합니다.

    • 조회 테이블명이 바로 직전에 생성했던 테이블 이름과 정확하게 호환되는지 대조합니다.

    • 만일 통신 오류 코드 401을 돌려받았다면 권한 인증 누락을 뜻하므로 토큰을 갱신해 보세요.

  4. 사용할 컬럼 식별: 정상 조회된 속성 데이터 배열 중 실질 비디오 정보 콘텐츠를 가리키고 있는 'files' 컬럼을 타겟으로 잡습니다. 매칭 대상 인덱스를 빌드하기 위해 아래 형태로 대상 어레이를 정의합니다.

# Assuming the columns are retrieved successfully
selected_columns = [columns[2]]  # Adjust the index based on the actual structure of the response

컬럼 정보를 무사히 취득했다면 뒤이어 테이블 상에서 시맨틱 검색 인덱스를 본격 생성할 단계로 나아갑니다.

6단계: Twelve Labs의 Marengo-2.6 비디오 임베딩 모델을 사용해 테이블 상의 검색 인덱스 생성

비디오 데이터를 영리하게 다룰 수 있는 고성능 검색 성능을 이식하기 위해, 먼저 Twelve Labs Marengo-2.6 임베딩 모델을 활용한 검색 인덱스를 구축해야 합니다. 각 데이터 유형에 최적화된 개별 임베딩 아키텍처가 활성화되도록 검색 인덱싱 스펙을 구성해 봅니다. 가이드는 다음과 같습니다.

  1. API 요청 설정: 아래 예시 코드를 실행해 검색 인덱스를 가동합니다. 직전 스크립트 블록에서 가져온 올바른 테이블 명칭과 세부 타겟 컬럼이 잘 전달되도록 준비하세요.

create_index_url = f"{base_api_url}/index/"
search_index_config = {
    "version": '1.0',
    "pdf": {
        "text_embedder_name": "jina-clip-v1",
        "image_embedder_name": "jina-clip-v1",
    },
    "text": {
        "embedder_name": "text-embedding-3-small",
    },
    "image": {
        "embedder_name": "jina-clip-v1",
    },
    "audio": {
        "embedder_name": 'None',
    },
    "video": {
        "embedder_name": "Marengo-retrieval-2.6",
    },
}

index_name = "my_search_index"  # Replace with your desired index name

form_data = {
    "name": index_name,
    "table_name": table_name,
    "id_column_name": "r_uuid",  # Replace with the actual ID column name if different
    "column_names": json.dumps(selected_columns),
    "search_index_config": json.dumps(search_index_config),
    "display_name": index_name,
}

response = requests.post(create_index_url, headers=headers, data=form_data)

if response.status_code == 201:
    print("Success")
else:
    print("Failure!")

index_id = response.json().get("id") if response.status_code == 201 else None
print(f"Index ID: {index_id}")
  1. 검색 인덱스 커스텀 셋업: 사전에 정의된 search_index_config 딕셔너리는 파일 유형에 매칭할 임베딩 엔진 스펙을 상세하게 기술한 객체입니다.

    • 텍스트(Text): 서술적 표현을 잘 파싱할 수 있게 "text-embedding-3-small"을 부착하여 대응합니다.

    • 비디오(Video): 풍부한 시네마틱 해석에 탁월한 "Marengo-retrieval-2.6" 엔진을 비디오 처리에 맞춤형으로 융합합니다. 해당 구조적 원리를 이해하고 싶다면 공식 스펙 시트를 참조하세요: https://docs.twelvelabs.io/docs/create-video-embeddings

    • PDF 및 이미지(Image): 대규모 이미지 인식에 검증된 멀티모달 모델 "jina-clip-v1"을 활용합니다.

    • 오디오(Audio): 이번 프로젝트 진행 영역에 포함되지 않으므로 'None'을 선언해 인덱싱 부하를 없앱니다. 오디오 임베딩이 작동하지 않아도 검색 기능에는 지장이 없습니다.

  2. 코드 작동: 파이썬 구동창에서 이 모듈을 가동합니다.

  3. 출력값 검증: 인덱싱 로직이 제대로 통과되면 화면상에 "Success"가 확인되며 실패 시 오류 구문과 실패 로그 코드가 발생합니다.

  4. 트러블슈팅 가이드: 비정상 에러 흐름을 통제하고 싶다면 다음 포인트를 리체크하세요.

    • 통신 요청에 탑재한 키 밸류의 옯고 그름 유무와 키 생성 시 인가된 스코프가 적당한지 재조회합니다.

    • 타겟 테이블과 선택한 컬럼 메타데이터 명칭이 단 한 글자의 오타 없이 매칭되어 있는지 더블 체크합니다.

    • 혹시 코드 201 이외의 응답이 반환되었다면 이는 전송 규정 누락을 가리키는 경우가 크므로 매뉴얼 서류 규칙과 포맷 요구사항을 검토해 주세요.

  5. 확보한 인덱스 ID: 정상적으로 빌드가 끝났다면 가동 창으로부터 생성된 Index ID 결과물이 노출되며, 향후 쿼리 실행 및 관련 데이터 세부 처리에서 메인 레퍼런스로 활용 가능합니다.

본 공정을 무사히 극복함으로써 고도로 연쇄 정렬된 Twelve Labs Marengo-2.6 엔진의 기능을 온전히 흡수시킬 수 있으며 정교한 시맨틱 비디오 질의 처리가 활성화됩니다.

7단계: 검색 인덱스 생성 상태 체크 및 대기 상태 확인

인덱스 빌드를 선언한 다음, 실시간 서버 내부에서 컴파일링 및 비디오 프레임 추출 처리가 안전히 마무리되기까지 일정 모니터링 주기가 수반되어야 합니다. 아래 단계를 따라 확인 프로세스를 수행하세요.

  1. API 요청 설정: 비디오 시퀀싱 데이터를 바쁘게 해독하고 있을 인덱서 엔진의 가도 완료 수준을 판정하기 위해 실시간 비동기 검사 스크립트를 구현합니다. 직전 스크립트에서 확인한 Index ID를 정확하게 할당해야 모니터링이 시작됩니다.

import time

check_status_url = f"{base_api_url}/index/{index_id}/status/"

max_retries = 120  # Maximum number of retries to check the status

# Start a loop to continuously check the status
for _ in range(max_retries):
    response = requests.get(check_status_url, headers=headers)

    if response.status_code == 200:
        status = response.json().get('status')

        # Check if the index creation is complete
        if status == 'SUCCESS':
            print("Index creation succeeded.")
            break
        elif status == 'FAILURE' or status == 'REVOKED':
            print("Index creation failed.")
            break

        print(f"Index status: {status}. Checking again in 10 seconds...")
        # Wait for 10 seconds before checking again
        time.sleep(10)
    else:
        print(f"Failed to get status: {response.status_code}")
        break
else:
    print("Max retries reached, exiting.")
  1. 실행 제어: 파이썬 테스트 도구 인프라에서 위의 지연 대기 연동 스크립트를 최종 가동합니다.

  2. 상태 모니터링: 코드 블록은 정상 프로세스가 종료될 때까지 최대 120회 간 주기를 갖고 10초 간격으로 서버 피드백 통신 로그를 수행하여 안정적인 대기 처리를 보장합니다.

  3. 리턴 값 판별:

    • 생성 상태가 SUCCESS 로 확인된다면 화면상에 "Index creation succeeded." 메시지가 프린팅되며 루프가 종료됩니다.

    • 시스템 비 정상 변수로 흐리멍덩한 루핑 실패나 FAILURE 혹은 REVOKED 꼬리가 출력될 때는 "Index creation failed." 실패 알람이 나타납니다.

    • 만일 현재 컴파일 중인 미완성 프로세스 진행 상황인 경우 현 상태 문자를 콘솔창에 찍어 현재 대기 상황 정보를 투명하게 갱신해 줍니다.

  4. 오류 확인 요령: 상태 확인 중 예상치 못한 버그를 마주했다면 하단 내역을 복기하세요.

    • 사용 토큰의 타겟 권한 지위가 이상 없는지, 계정 내 리소스 바인딩이 꼬이진 않았는지 살펴보세요.

    • 체크 중인 Index ID 대상 고유 키 값이 잘못 전달되지는 않았는지 검증합니다.

  5. 최대 반복 카운트 이탈: 만약 120번의 루프 완료까지 변동점이 없는 비정상 진행 상태가 방치될 때 툴에는 "Max retries reached, exiting."이 도출됩니다. 인코딩 스택 프로세싱 부하가 상상 이상으로 적체되어 있는 상태임을 예측해 볼 수 있습니다.

이로써 비디오 시맨틱 인덱스 구축 결과 안정성 진단을 깔끔하게 끝마쳤습니다. 대기열 확인이 정상 처리되었다면 다음 질의 파트로 당당히 넘어갈 준비가 모두 해결되었습니다.

8단계: 검색 목적과 입력 쿼리에 따른 정밀 비디오 자료 쿼리 검색 가동

드디어 비디오 컬렉션 탐색 인덱서 구조를 완성하고 완전한 검증을 넘었으니, 실사용 목적에 대응하는 테스트 쿼리를 던져 조건과 문장 상황에 맞춰 반응하는 고유 시맨틱 비디오를 찾아낼 순간입니다. 연산 질의 처리를 아래 형태로 개시해 보십시오.

  1. API 요청 설정: 아래 기술된 테스팅 질의용 스크립트 모듈을 준비하세요. 이전 검사를 끝낸 바로 그 활성화 완료 상태의 Index ID를 변수로 입력해 주셔야 작동합니다.

search_index_url = f"{base_api_url}/index/{index_id}/search/"

form_data = {
    "query": "tennis on grass",  # Replace with your search query
    "limit": "10"  # Optional: Limit the number of results returned
}

response = requests.post(search_index_url, headers=headers, data=form_data)

results = response.json().get("result_rows")

print("Videos from most to least relevant:\n")
for idx, result in enumerate(results):
    print(f"{idx + 1}: {result[1]}")
  1. 질의 커스텀하기: form_data 구문 속 정의된 "tennis on grass"(잔디밭 위 테니스) 대신, 상상 가능한 비디오 신 특징이나 씬 묘사를 영문 문자열 형태로 자유롭게 매핑해 보세요. 연동 결과 개수 제한을 걸고 싶다면 limit 파라미터를 적당한 정수 문자 값으로 조정해주면 제어됩니다.

  2. 실행 가동: 작성 도구 내에서 해당 파이썬 호출 인터페이스 코드를 동작하도록 구동합니다.

  3. 출력값 검증: 기동 시 시스템에 입력된 쿼리 질의 구조를 전달하여 결과 어레이를 끌어옵니다. 무사히 완수될 경우 일치율과 콘셉트 연관성에 따라 가깝게 매칭되는 비디오 순위를 가중치 순으로 바르게 노출해 줍니다.

  4. 결과값 판독 요령: 리턴된 개체 시퀀스는 순서별로 줄지어 나타나며, 시맨틱 문맥 매칭 상태가 높은 리소스 파일이 1번에서부터 표시됩니다. 현 구현 가이드는 결과 튜플의 후속 인자가 적정한 메타 속성 포맷(비디오 url 혹은 상세 타이틀)을 품고 있는 가정하에 설계되었습니다. 리스폰 구조가 상이한 구조인 경우 대상 인덱스 데이터 인덱싱 슬라이싱 변인을 다듬으십시오.

  5. 트러블슈팅 가이드: 만일 예측 외 난관에 부딪혔다면 다음 해결 실마리를 탐독하십시오.

    • 전송 타겟에 가미된 통신 토큰 권한 데이터 스펙에 이상 및 만료 상황이 없는지 실시간 확인하십시오.

    • 호출 대상으로 선택한 고유 활성화 Index ID 주소가 맞는지 조망하고 빌드 및 배포 완료 여부가 클린한지 살핍니다.

전과정을 성공적으로 완주함으로써 지능화된 Twelve Labs Embed API 구조를 Roe AI 데이터 전처리 체계에 멋지게 융합하여 인위적인 태깅 과정 없이 고퀄리티 시맨틱 탐색 서비스를 작동시키는 신세계를 맞이하게 되었습니다.

결론

본 가이드에서는 Twelve Labs의 비디오 임베딩 능력과 Roe AI의 데이터 관리 능력을 밀착 가동하여, 비디오 시각 정보의 함의와 복합 정황을 맥락대로 추출하여 질의에 맞춤 응답하는 지능형 검색 프레임워크를 개발하는 핵심 공정을 설명했습니다. 이 단계를 충실히 완수한 개발자라면 차세대 기술 트렌드로 자리 매김할 의미 기반 멀티모달 서비스 구성의 강력한 응용 기초를 확보하게 된 셈입니다.

개발자에게 있어 이번 두 기술 플랫폼의 유기적인 만남은 미래형 비디오 컴퓨팅 구축을 가속하는 시발점이 되어 줍니다. Twelve Labs가 품은 디테일한 비디오 영상 맥락 인지 신경망 알고리즘과 Roe AI가 조율하는 유동적인 관계형 데이터 관리 메커니즘을 융합함으로써, 상상에 그쳤던 상황 주도형 멀티모달 솔루션을 매우 수월하고 기민하게 제작할 수 있게 되었습니다.

여기서 그치지 말고, 이 유연한 구조를 어떻게 본인 고유의 실무 시나리오에 응용하고 변용할지 상상력을 확장해 보세요. 사용자의 활동 및 시청 로그에 긴밀히 반응하는 유동형 미디어 추천 시스템, 대용량 아카이브를 자율 수집 및 가이드 진단하는 비디오 인텔리전스 레이블 생성 파이프라인 등, 이번 시너지는 풍요로운 멀티미디어 도메인의 도약에 훌륭하고 주춧돌 같은 디딤돌 역할을 지원해 줄 것입니다.

부록

학습과 개발 과정에서 언제든 활용할 수 있는 추가적인 리소스입니다.

  1. 전과정 동작 코드가 망라된 Colab 노트북

  2. Twelve Labs 공식 API 문서

  3. Roe AI 개발 가이드 서재

여러분이 이번 튜토리얼을 통해 어떤 혁신적인 서비스를 만들어낼지 무척 기대됩니다. 멋진 아이디어와 멋진 작품들을 Twelve Labs와 Roe AI 커뮤니티에 적극 공유해 주세요. 즐거운 개발 되시길 바랍니다!

요약: 이 튜토리얼은 Twelve Labs의 Embed API를 Roe AI 플랫폼과 통합하여 강력한 시맨틱 비디오 검색 솔루션을 만드는 방법을 보여줍니다. 가이드를 따라가며 개발자는 최첨단 비디오 임베딩을 기반으로 정확하고 컨텍스트를 이해하는 비디오 검색 시스템을 빠르게 구축할 수 있습니다. 이 튜토리얼을 위해 함께 협업해 준 Roe AI 팀(Sam LiangRichard Meng)에 감사의 말씀을 전합니다.

소개

이 튜토리얼은 Twelve Labs의 Embed APIRoe AI의 SQL 기반 AI 플랫폼과 통합하여 개발자에게 더 고도화된 비디오 이해 도구를 제공하는 데 집중합니다. 이번 통합은 Twelve Labs의 비디오 임베딩 모델과 Roe AI의 데이터 관리 및 검색 기능을 결합하여 정교한 비디오 검색 솔루션을 구축할 수 있게 도와줍니다.

개발자는 이 통합을 활용해 비디오 데이터 내 여러 모달리티 전반에서 컨텍스트, 콘텐츠, 뉘앙스를 이해하는 애플리케이션을 빌드하는 방법을 배우게 됩니다. 또한 복잡한 비디오 데이터를 다루는 과정을 단순화하고, 비디오 검색 기능의 정확도와 효율성을 어떻게 극대화할 수 있는지 탐구합니다. 콘텐츠 플랫폼, 비디오 분석 도구 또는 비디오 데이터를 다루는 어떠한 프로젝트를 개발 중이든, 실제 프로젝트에 이러한 기술을 적용할 수 있는 유용한 인사이트를 얻을 수 있습니다.

1단계: app.roe-ai.com에서 API 토큰 발급받기

Roe AI를 시작하려면 요청을 인증하는 데 필요한 API 토큰을 발급받아야 합니다. 아래 단계에 따라 API 토큰을 확인하세요.

  1. 가입 및 로그인: app.roe-ai.com에 접속하여 새 계정을 만들거나 기존 계정으로 로그인합니다.

  2. API 설정 이동: 로그인 후 API 설정 또는 계정 설정 페이지로 이동하여 API 토큰을 생성하거나 확인할 수 있는 메뉴를 찾습니다.

  3. API 토큰 복사: 생성된 토큰을 클립보드에 복사합니다. 이 토큰은 API 요청 시 계속 사용되므로 안전하게 보관하세요.

  4. 코드에 토큰 적용: 아래 코드 스니펫을 사용하여 API 요청을 위한 헤더를 설정합니다. <Your API Token> 부분을 복사한 실제 토큰으로 대체하세요.

import requests
import json

headers = {
  'Authorization': 'Bearer <Your API Token>'
}

base_api_url = "https://api.roe-ai.com/v1"

이제 토큰 확인이 완료되었으므로, 다음 단계에서 Roe AI API를 사용할 준비가 끝났습니다.

2단계: 비디오 저장을 위한 Roe 데이터 세트 생성

비디오 파일을 Roe AI에 저장하려면 먼저 데이터 세트를 만들어야 합니다. 아래 단계에 따라 새 데이터 세트를 생성하세요.

  1. 데이터 세트 이름 지정: 나중에 쉽게 알아볼 수 있도록 데이터 세트 이름을 지정합니다. 이 가이드에서는 "My Video Dataset"을 사용하며, 원하시는 이름으로 자유롭게 변경하셔도 좋습니다.

  2. API 요청 설정: 아래 코드 스니펫을 사용하여 데이터 세트를 생성합니다. 1단계에서 준비한 헤더와 base API URL이 적용되었는지 확인하세요.

create_dataset_url = f"{base_api_url}/datasets/"

dataset_name = "My Video Dataset"  # Replace with your dataset name

form_data = {
    "name": dataset_name
}

response = requests.post(create_dataset_url, headers=headers, data=form_data)

if response.status_code == 201:
    print("Success")
else:
    print("Failure!")

dataset_id = response.json().get("id") if response.status_code == 201 else None

print(f"Dataset ID: {dataset_id}")
  1. 코드 실행: 준비된 파이썬(Python) 환경에서 코드 스니펫을 실행합니다.

  2. 응답 확인: 데이터 세트가 성공적으로 생성되면 콘솔에 "Success"와 함께 Dataset ID가 출력됩니다. 실패할 경우 "Failure!"가 출력되며 Dataset ID는 None이 됩니다.

  3. 트러블슈팅: 만약 문제가 발생한다면 API 토큰이 올바른지, Roe AI에서 데이터 세트를 생성할 수 있는 권한이 있는지 확인하세요.

데이터 세트가 성공적으로 만들어졌다면 다음 단계인 비디오 파일 업로드로 넘어갑니다.

‍3단계: 생성된 Roe 데이터 세트에 비디오 파일 업로드

데이터 세트 준비를 마쳤으니 이제 비디오 파일을 업로드할 차례입니다. 아래 단계에 따라 비디오를 업로드해 보세요.

  1. 비디오 파일 준비: 업로드할 비디오 파일들이 잘 준비되었는지 확인합니다. 이 예제에서는 "/path/to/video1.mp4" 경로에 "video1.mp4" 파일이 존재한다고 가정합니다.

  2. API 요청 설정: 아래 코드 스니펫을 활용해 비디오 파일을 데이터 세트에 업로드합니다. 이전 단계에서 확인한 Dataset ID를 미리 준비해 두어야 합니다.

upload_files_url = f"{base_api_url}/datasets/files/upload/"

payload = {
    'dataset_id': f"{dataset_id}",
}

# REQUIRED: Add all your VIDEO FILES HERE
files = [
    ('file', ('video1.mp4', open('/path/to/video1.mp4', 'rb'), 'video/mp4')),
    # Add more files as needed
]

response = requests.request("POST", upload_files_url, headers=headers, data=payload, files=files)

if response.status_code == 200:
    print("Success")
else:
    print("Failure!")
  1. 파일 상세 정보 수정: 'video1.mp4' 부분을 실제 비디오 파일명으로 변경하고, '/path/to/video1.mp4' 경로를 로컬 컴퓨터의 실제 경로로 수정합니다. 여러 비디오를 한 번에 업로드하려면 files 리스트에 요소를 추가하면 됩니다.

  2. 코드 실행: 실행 환경에서 해당 파이썬 코드를 구동합니다.

  3. 응답 확인: 업로드가 성공하면 콘솔에 "Success"가 찍힙니다. 에러가 발생한 경우 "Failure!"가 표시됩니다.

  4. 트러블슈팅: 문제가 있다면 API 토큰 유효성, Dataset ID가 일치하는지, 해당 데이터 세트에 파일을 추가할 권한이 활성화되어 있는지 점검하세요.

비디오 파일이 정상적으로 업로드되었다면, 다음 단계에서 데이터 세트를 기반으로 한 테이블을 생성해 보겠습니다.

‍4단계: Roe 데이터 세트에서 테이블 생성

업로드한 비디오 파일들을 기반으로 테이블을 빌드할 차례입니다. 이 테이블은 시맨틱 비디오 검색 서비스의 동작 구조적 뼈대가 됩니다. 다음 단계를 활용하세요.

  1. 테이블 이름 정하기: 직관적으로 식별할 수 있는 테이블 이름을 입력합니다. 여기서는 "my_video_table"을 사용합니다. 이름 지정 시 하이픈(``)은 포함하지 않도록 주의하세요.

  2. API 요청 설정: 아래 코드를 사용해 업로드한 데이터 세트 경로에서 테이블 생성을 호출합니다. 이전 단계의 Dataset ID가 바르게 적용되어 있어야 합니다.

create_table_url = f"{base_api_url}/database/table/import/roe-dataset/"

table_name = "my_video_table"  # Replace with your desired table name

form_data = {
    "table_name": table_name,
    "dataset_id": f"{dataset_id}",
    "sync_dataset": "false",  # Set to "true" if you want to sync the dataset with the table
}

response = requests.post(create_table_url, headers=headers, data=form_data)

if response.status_code == 200:
    print("Success")
else:
    print("Failure!")
  1. 데이터 세트 동기화 옵션: sync_dataset 파라미터는 테이블 데이터를 실시간으로 데이터 세트 현황과 매칭시킬지 결정하는 플래그입니다. "true" 변경 시 원본 데이터 세트 변동 사항이 테이블 데이터에도 지속 반영됩니다. 편의상 이 튜토리얼은 "false"로 유지합니다.

  2. 코드 실행: 파이썬 상에서 코드를 동작시킵니다.

  3. 응답 확인: 테이블 구성이 완료되면 화면에 "Success"가 출력되고 실패 시 "Failure!"가 나타납니다.

  4. 트러블슈팅: 호출에 차질이 발생한다면 토큰 정보, Dataset ID, 계정의 테이블 생성 권한 등을 다시 한번 면밀히 체크하세요.

결과가 문제없다면 데이터 구조를 탐색하기 위해 컬럼을 확인해 볼 수 있습니다.

‍5단계: 사용 가능한 데이터 확인을 위해 테이블 컬럼 조회

테이블 내 속성들을 명확히 설계하고 검색 인덱스를 정밀 조준하기 위해서, 테이블에 어떤 컬럼이 포함되어 있는지 확인해야 합니다. 아래 단계를 시도하세요.

  1. API 요청 설정: 생성된 대상 테이블에서 컬럼을 가져오도록 아래 코드를 세ッティング합니다. 이전 단계의 정확한 테이블 이름이 매겨져야 타겟 컬럼 정보를 파악하기 원활합니다.

table_cols_url = f"{base_api_url}/database/table/{table_name}/columns"

response = requests.get(table_cols_url, headers=headers)

if response.status_code == 200:
    columns = response.json()  # Parsing the JSON response
    print("Success")
    print("Columns:", columns)
else:
    print("Failure! Status Code:", response.status_code)
  1. 코드 실행: 개발 창에서 파이썬 코드를 동작시킵니다.

  2. 응답 확인: 확인이 성공하면 "Success"와 함께 테이블 컬럼 데이터의 구조 목록이 출력됩니다. 실패하는 경우에는 현재 발생한 Status Code가 명시된 에러 로그 메시지가 출력됩니다.

  3. 트러블슈팅: 비정상 동작을 막으려면 다음 지표를 살펴보세요.

    • 사용하고 계신 API 토큰의 권한 만료 여부 및 인증 통과 여부를 검토합니다.

    • 조회 테이블명이 바로 직전에 생성했던 테이블 이름과 정확하게 호환되는지 대조합니다.

    • 만일 통신 오류 코드 401을 돌려받았다면 권한 인증 누락을 뜻하므로 토큰을 갱신해 보세요.

  4. 사용할 컬럼 식별: 정상 조회된 속성 데이터 배열 중 실질 비디오 정보 콘텐츠를 가리키고 있는 'files' 컬럼을 타겟으로 잡습니다. 매칭 대상 인덱스를 빌드하기 위해 아래 형태로 대상 어레이를 정의합니다.

# Assuming the columns are retrieved successfully
selected_columns = [columns[2]]  # Adjust the index based on the actual structure of the response

컬럼 정보를 무사히 취득했다면 뒤이어 테이블 상에서 시맨틱 검색 인덱스를 본격 생성할 단계로 나아갑니다.

6단계: Twelve Labs의 Marengo-2.6 비디오 임베딩 모델을 사용해 테이블 상의 검색 인덱스 생성

비디오 데이터를 영리하게 다룰 수 있는 고성능 검색 성능을 이식하기 위해, 먼저 Twelve Labs Marengo-2.6 임베딩 모델을 활용한 검색 인덱스를 구축해야 합니다. 각 데이터 유형에 최적화된 개별 임베딩 아키텍처가 활성화되도록 검색 인덱싱 스펙을 구성해 봅니다. 가이드는 다음과 같습니다.

  1. API 요청 설정: 아래 예시 코드를 실행해 검색 인덱스를 가동합니다. 직전 스크립트 블록에서 가져온 올바른 테이블 명칭과 세부 타겟 컬럼이 잘 전달되도록 준비하세요.

create_index_url = f"{base_api_url}/index/"
search_index_config = {
    "version": '1.0',
    "pdf": {
        "text_embedder_name": "jina-clip-v1",
        "image_embedder_name": "jina-clip-v1",
    },
    "text": {
        "embedder_name": "text-embedding-3-small",
    },
    "image": {
        "embedder_name": "jina-clip-v1",
    },
    "audio": {
        "embedder_name": 'None',
    },
    "video": {
        "embedder_name": "Marengo-retrieval-2.6",
    },
}

index_name = "my_search_index"  # Replace with your desired index name

form_data = {
    "name": index_name,
    "table_name": table_name,
    "id_column_name": "r_uuid",  # Replace with the actual ID column name if different
    "column_names": json.dumps(selected_columns),
    "search_index_config": json.dumps(search_index_config),
    "display_name": index_name,
}

response = requests.post(create_index_url, headers=headers, data=form_data)

if response.status_code == 201:
    print("Success")
else:
    print("Failure!")

index_id = response.json().get("id") if response.status_code == 201 else None
print(f"Index ID: {index_id}")
  1. 검색 인덱스 커스텀 셋업: 사전에 정의된 search_index_config 딕셔너리는 파일 유형에 매칭할 임베딩 엔진 스펙을 상세하게 기술한 객체입니다.

    • 텍스트(Text): 서술적 표현을 잘 파싱할 수 있게 "text-embedding-3-small"을 부착하여 대응합니다.

    • 비디오(Video): 풍부한 시네마틱 해석에 탁월한 "Marengo-retrieval-2.6" 엔진을 비디오 처리에 맞춤형으로 융합합니다. 해당 구조적 원리를 이해하고 싶다면 공식 스펙 시트를 참조하세요: https://docs.twelvelabs.io/docs/create-video-embeddings

    • PDF 및 이미지(Image): 대규모 이미지 인식에 검증된 멀티모달 모델 "jina-clip-v1"을 활용합니다.

    • 오디오(Audio): 이번 프로젝트 진행 영역에 포함되지 않으므로 'None'을 선언해 인덱싱 부하를 없앱니다. 오디오 임베딩이 작동하지 않아도 검색 기능에는 지장이 없습니다.

  2. 코드 작동: 파이썬 구동창에서 이 모듈을 가동합니다.

  3. 출력값 검증: 인덱싱 로직이 제대로 통과되면 화면상에 "Success"가 확인되며 실패 시 오류 구문과 실패 로그 코드가 발생합니다.

  4. 트러블슈팅 가이드: 비정상 에러 흐름을 통제하고 싶다면 다음 포인트를 리체크하세요.

    • 통신 요청에 탑재한 키 밸류의 옯고 그름 유무와 키 생성 시 인가된 스코프가 적당한지 재조회합니다.

    • 타겟 테이블과 선택한 컬럼 메타데이터 명칭이 단 한 글자의 오타 없이 매칭되어 있는지 더블 체크합니다.

    • 혹시 코드 201 이외의 응답이 반환되었다면 이는 전송 규정 누락을 가리키는 경우가 크므로 매뉴얼 서류 규칙과 포맷 요구사항을 검토해 주세요.

  5. 확보한 인덱스 ID: 정상적으로 빌드가 끝났다면 가동 창으로부터 생성된 Index ID 결과물이 노출되며, 향후 쿼리 실행 및 관련 데이터 세부 처리에서 메인 레퍼런스로 활용 가능합니다.

본 공정을 무사히 극복함으로써 고도로 연쇄 정렬된 Twelve Labs Marengo-2.6 엔진의 기능을 온전히 흡수시킬 수 있으며 정교한 시맨틱 비디오 질의 처리가 활성화됩니다.

7단계: 검색 인덱스 생성 상태 체크 및 대기 상태 확인

인덱스 빌드를 선언한 다음, 실시간 서버 내부에서 컴파일링 및 비디오 프레임 추출 처리가 안전히 마무리되기까지 일정 모니터링 주기가 수반되어야 합니다. 아래 단계를 따라 확인 프로세스를 수행하세요.

  1. API 요청 설정: 비디오 시퀀싱 데이터를 바쁘게 해독하고 있을 인덱서 엔진의 가도 완료 수준을 판정하기 위해 실시간 비동기 검사 스크립트를 구현합니다. 직전 스크립트에서 확인한 Index ID를 정확하게 할당해야 모니터링이 시작됩니다.

import time

check_status_url = f"{base_api_url}/index/{index_id}/status/"

max_retries = 120  # Maximum number of retries to check the status

# Start a loop to continuously check the status
for _ in range(max_retries):
    response = requests.get(check_status_url, headers=headers)

    if response.status_code == 200:
        status = response.json().get('status')

        # Check if the index creation is complete
        if status == 'SUCCESS':
            print("Index creation succeeded.")
            break
        elif status == 'FAILURE' or status == 'REVOKED':
            print("Index creation failed.")
            break

        print(f"Index status: {status}. Checking again in 10 seconds...")
        # Wait for 10 seconds before checking again
        time.sleep(10)
    else:
        print(f"Failed to get status: {response.status_code}")
        break
else:
    print("Max retries reached, exiting.")
  1. 실행 제어: 파이썬 테스트 도구 인프라에서 위의 지연 대기 연동 스크립트를 최종 가동합니다.

  2. 상태 모니터링: 코드 블록은 정상 프로세스가 종료될 때까지 최대 120회 간 주기를 갖고 10초 간격으로 서버 피드백 통신 로그를 수행하여 안정적인 대기 처리를 보장합니다.

  3. 리턴 값 판별:

    • 생성 상태가 SUCCESS 로 확인된다면 화면상에 "Index creation succeeded." 메시지가 프린팅되며 루프가 종료됩니다.

    • 시스템 비 정상 변수로 흐리멍덩한 루핑 실패나 FAILURE 혹은 REVOKED 꼬리가 출력될 때는 "Index creation failed." 실패 알람이 나타납니다.

    • 만일 현재 컴파일 중인 미완성 프로세스 진행 상황인 경우 현 상태 문자를 콘솔창에 찍어 현재 대기 상황 정보를 투명하게 갱신해 줍니다.

  4. 오류 확인 요령: 상태 확인 중 예상치 못한 버그를 마주했다면 하단 내역을 복기하세요.

    • 사용 토큰의 타겟 권한 지위가 이상 없는지, 계정 내 리소스 바인딩이 꼬이진 않았는지 살펴보세요.

    • 체크 중인 Index ID 대상 고유 키 값이 잘못 전달되지는 않았는지 검증합니다.

  5. 최대 반복 카운트 이탈: 만약 120번의 루프 완료까지 변동점이 없는 비정상 진행 상태가 방치될 때 툴에는 "Max retries reached, exiting."이 도출됩니다. 인코딩 스택 프로세싱 부하가 상상 이상으로 적체되어 있는 상태임을 예측해 볼 수 있습니다.

이로써 비디오 시맨틱 인덱스 구축 결과 안정성 진단을 깔끔하게 끝마쳤습니다. 대기열 확인이 정상 처리되었다면 다음 질의 파트로 당당히 넘어갈 준비가 모두 해결되었습니다.

8단계: 검색 목적과 입력 쿼리에 따른 정밀 비디오 자료 쿼리 검색 가동

드디어 비디오 컬렉션 탐색 인덱서 구조를 완성하고 완전한 검증을 넘었으니, 실사용 목적에 대응하는 테스트 쿼리를 던져 조건과 문장 상황에 맞춰 반응하는 고유 시맨틱 비디오를 찾아낼 순간입니다. 연산 질의 처리를 아래 형태로 개시해 보십시오.

  1. API 요청 설정: 아래 기술된 테스팅 질의용 스크립트 모듈을 준비하세요. 이전 검사를 끝낸 바로 그 활성화 완료 상태의 Index ID를 변수로 입력해 주셔야 작동합니다.

search_index_url = f"{base_api_url}/index/{index_id}/search/"

form_data = {
    "query": "tennis on grass",  # Replace with your search query
    "limit": "10"  # Optional: Limit the number of results returned
}

response = requests.post(search_index_url, headers=headers, data=form_data)

results = response.json().get("result_rows")

print("Videos from most to least relevant:\n")
for idx, result in enumerate(results):
    print(f"{idx + 1}: {result[1]}")
  1. 질의 커스텀하기: form_data 구문 속 정의된 "tennis on grass"(잔디밭 위 테니스) 대신, 상상 가능한 비디오 신 특징이나 씬 묘사를 영문 문자열 형태로 자유롭게 매핑해 보세요. 연동 결과 개수 제한을 걸고 싶다면 limit 파라미터를 적당한 정수 문자 값으로 조정해주면 제어됩니다.

  2. 실행 가동: 작성 도구 내에서 해당 파이썬 호출 인터페이스 코드를 동작하도록 구동합니다.

  3. 출력값 검증: 기동 시 시스템에 입력된 쿼리 질의 구조를 전달하여 결과 어레이를 끌어옵니다. 무사히 완수될 경우 일치율과 콘셉트 연관성에 따라 가깝게 매칭되는 비디오 순위를 가중치 순으로 바르게 노출해 줍니다.

  4. 결과값 판독 요령: 리턴된 개체 시퀀스는 순서별로 줄지어 나타나며, 시맨틱 문맥 매칭 상태가 높은 리소스 파일이 1번에서부터 표시됩니다. 현 구현 가이드는 결과 튜플의 후속 인자가 적정한 메타 속성 포맷(비디오 url 혹은 상세 타이틀)을 품고 있는 가정하에 설계되었습니다. 리스폰 구조가 상이한 구조인 경우 대상 인덱스 데이터 인덱싱 슬라이싱 변인을 다듬으십시오.

  5. 트러블슈팅 가이드: 만일 예측 외 난관에 부딪혔다면 다음 해결 실마리를 탐독하십시오.

    • 전송 타겟에 가미된 통신 토큰 권한 데이터 스펙에 이상 및 만료 상황이 없는지 실시간 확인하십시오.

    • 호출 대상으로 선택한 고유 활성화 Index ID 주소가 맞는지 조망하고 빌드 및 배포 완료 여부가 클린한지 살핍니다.

전과정을 성공적으로 완주함으로써 지능화된 Twelve Labs Embed API 구조를 Roe AI 데이터 전처리 체계에 멋지게 융합하여 인위적인 태깅 과정 없이 고퀄리티 시맨틱 탐색 서비스를 작동시키는 신세계를 맞이하게 되었습니다.

결론

본 가이드에서는 Twelve Labs의 비디오 임베딩 능력과 Roe AI의 데이터 관리 능력을 밀착 가동하여, 비디오 시각 정보의 함의와 복합 정황을 맥락대로 추출하여 질의에 맞춤 응답하는 지능형 검색 프레임워크를 개발하는 핵심 공정을 설명했습니다. 이 단계를 충실히 완수한 개발자라면 차세대 기술 트렌드로 자리 매김할 의미 기반 멀티모달 서비스 구성의 강력한 응용 기초를 확보하게 된 셈입니다.

개발자에게 있어 이번 두 기술 플랫폼의 유기적인 만남은 미래형 비디오 컴퓨팅 구축을 가속하는 시발점이 되어 줍니다. Twelve Labs가 품은 디테일한 비디오 영상 맥락 인지 신경망 알고리즘과 Roe AI가 조율하는 유동적인 관계형 데이터 관리 메커니즘을 융합함으로써, 상상에 그쳤던 상황 주도형 멀티모달 솔루션을 매우 수월하고 기민하게 제작할 수 있게 되었습니다.

여기서 그치지 말고, 이 유연한 구조를 어떻게 본인 고유의 실무 시나리오에 응용하고 변용할지 상상력을 확장해 보세요. 사용자의 활동 및 시청 로그에 긴밀히 반응하는 유동형 미디어 추천 시스템, 대용량 아카이브를 자율 수집 및 가이드 진단하는 비디오 인텔리전스 레이블 생성 파이프라인 등, 이번 시너지는 풍요로운 멀티미디어 도메인의 도약에 훌륭하고 주춧돌 같은 디딤돌 역할을 지원해 줄 것입니다.

부록

학습과 개발 과정에서 언제든 활용할 수 있는 추가적인 리소스입니다.

  1. 전과정 동작 코드가 망라된 Colab 노트북

  2. Twelve Labs 공식 API 문서

  3. Roe AI 개발 가이드 서재

여러분이 이번 튜토리얼을 통해 어떤 혁신적인 서비스를 만들어낼지 무척 기대됩니다. 멋진 아이디어와 멋진 작품들을 Twelve Labs와 Roe AI 커뮤니티에 적극 공유해 주세요. 즐거운 개발 되시길 바랍니다!

요약: 이 튜토리얼은 Twelve Labs의 Embed API를 Roe AI 플랫폼과 통합하여 강력한 시맨틱 비디오 검색 솔루션을 만드는 방법을 보여줍니다. 가이드를 따라가며 개발자는 최첨단 비디오 임베딩을 기반으로 정확하고 컨텍스트를 이해하는 비디오 검색 시스템을 빠르게 구축할 수 있습니다. 이 튜토리얼을 위해 함께 협업해 준 Roe AI 팀(Sam LiangRichard Meng)에 감사의 말씀을 전합니다.

소개

이 튜토리얼은 Twelve Labs의 Embed APIRoe AI의 SQL 기반 AI 플랫폼과 통합하여 개발자에게 더 고도화된 비디오 이해 도구를 제공하는 데 집중합니다. 이번 통합은 Twelve Labs의 비디오 임베딩 모델과 Roe AI의 데이터 관리 및 검색 기능을 결합하여 정교한 비디오 검색 솔루션을 구축할 수 있게 도와줍니다.

개발자는 이 통합을 활용해 비디오 데이터 내 여러 모달리티 전반에서 컨텍스트, 콘텐츠, 뉘앙스를 이해하는 애플리케이션을 빌드하는 방법을 배우게 됩니다. 또한 복잡한 비디오 데이터를 다루는 과정을 단순화하고, 비디오 검색 기능의 정확도와 효율성을 어떻게 극대화할 수 있는지 탐구합니다. 콘텐츠 플랫폼, 비디오 분석 도구 또는 비디오 데이터를 다루는 어떠한 프로젝트를 개발 중이든, 실제 프로젝트에 이러한 기술을 적용할 수 있는 유용한 인사이트를 얻을 수 있습니다.

1단계: app.roe-ai.com에서 API 토큰 발급받기

Roe AI를 시작하려면 요청을 인증하는 데 필요한 API 토큰을 발급받아야 합니다. 아래 단계에 따라 API 토큰을 확인하세요.

  1. 가입 및 로그인: app.roe-ai.com에 접속하여 새 계정을 만들거나 기존 계정으로 로그인합니다.

  2. API 설정 이동: 로그인 후 API 설정 또는 계정 설정 페이지로 이동하여 API 토큰을 생성하거나 확인할 수 있는 메뉴를 찾습니다.

  3. API 토큰 복사: 생성된 토큰을 클립보드에 복사합니다. 이 토큰은 API 요청 시 계속 사용되므로 안전하게 보관하세요.

  4. 코드에 토큰 적용: 아래 코드 스니펫을 사용하여 API 요청을 위한 헤더를 설정합니다. <Your API Token> 부분을 복사한 실제 토큰으로 대체하세요.

import requests
import json

headers = {
  'Authorization': 'Bearer <Your API Token>'
}

base_api_url = "https://api.roe-ai.com/v1"

이제 토큰 확인이 완료되었으므로, 다음 단계에서 Roe AI API를 사용할 준비가 끝났습니다.

2단계: 비디오 저장을 위한 Roe 데이터 세트 생성

비디오 파일을 Roe AI에 저장하려면 먼저 데이터 세트를 만들어야 합니다. 아래 단계에 따라 새 데이터 세트를 생성하세요.

  1. 데이터 세트 이름 지정: 나중에 쉽게 알아볼 수 있도록 데이터 세트 이름을 지정합니다. 이 가이드에서는 "My Video Dataset"을 사용하며, 원하시는 이름으로 자유롭게 변경하셔도 좋습니다.

  2. API 요청 설정: 아래 코드 스니펫을 사용하여 데이터 세트를 생성합니다. 1단계에서 준비한 헤더와 base API URL이 적용되었는지 확인하세요.

create_dataset_url = f"{base_api_url}/datasets/"

dataset_name = "My Video Dataset"  # Replace with your dataset name

form_data = {
    "name": dataset_name
}

response = requests.post(create_dataset_url, headers=headers, data=form_data)

if response.status_code == 201:
    print("Success")
else:
    print("Failure!")

dataset_id = response.json().get("id") if response.status_code == 201 else None

print(f"Dataset ID: {dataset_id}")
  1. 코드 실행: 준비된 파이썬(Python) 환경에서 코드 스니펫을 실행합니다.

  2. 응답 확인: 데이터 세트가 성공적으로 생성되면 콘솔에 "Success"와 함께 Dataset ID가 출력됩니다. 실패할 경우 "Failure!"가 출력되며 Dataset ID는 None이 됩니다.

  3. 트러블슈팅: 만약 문제가 발생한다면 API 토큰이 올바른지, Roe AI에서 데이터 세트를 생성할 수 있는 권한이 있는지 확인하세요.

데이터 세트가 성공적으로 만들어졌다면 다음 단계인 비디오 파일 업로드로 넘어갑니다.

‍3단계: 생성된 Roe 데이터 세트에 비디오 파일 업로드

데이터 세트 준비를 마쳤으니 이제 비디오 파일을 업로드할 차례입니다. 아래 단계에 따라 비디오를 업로드해 보세요.

  1. 비디오 파일 준비: 업로드할 비디오 파일들이 잘 준비되었는지 확인합니다. 이 예제에서는 "/path/to/video1.mp4" 경로에 "video1.mp4" 파일이 존재한다고 가정합니다.

  2. API 요청 설정: 아래 코드 스니펫을 활용해 비디오 파일을 데이터 세트에 업로드합니다. 이전 단계에서 확인한 Dataset ID를 미리 준비해 두어야 합니다.

upload_files_url = f"{base_api_url}/datasets/files/upload/"

payload = {
    'dataset_id': f"{dataset_id}",
}

# REQUIRED: Add all your VIDEO FILES HERE
files = [
    ('file', ('video1.mp4', open('/path/to/video1.mp4', 'rb'), 'video/mp4')),
    # Add more files as needed
]

response = requests.request("POST", upload_files_url, headers=headers, data=payload, files=files)

if response.status_code == 200:
    print("Success")
else:
    print("Failure!")
  1. 파일 상세 정보 수정: 'video1.mp4' 부분을 실제 비디오 파일명으로 변경하고, '/path/to/video1.mp4' 경로를 로컬 컴퓨터의 실제 경로로 수정합니다. 여러 비디오를 한 번에 업로드하려면 files 리스트에 요소를 추가하면 됩니다.

  2. 코드 실행: 실행 환경에서 해당 파이썬 코드를 구동합니다.

  3. 응답 확인: 업로드가 성공하면 콘솔에 "Success"가 찍힙니다. 에러가 발생한 경우 "Failure!"가 표시됩니다.

  4. 트러블슈팅: 문제가 있다면 API 토큰 유효성, Dataset ID가 일치하는지, 해당 데이터 세트에 파일을 추가할 권한이 활성화되어 있는지 점검하세요.

비디오 파일이 정상적으로 업로드되었다면, 다음 단계에서 데이터 세트를 기반으로 한 테이블을 생성해 보겠습니다.

‍4단계: Roe 데이터 세트에서 테이블 생성

업로드한 비디오 파일들을 기반으로 테이블을 빌드할 차례입니다. 이 테이블은 시맨틱 비디오 검색 서비스의 동작 구조적 뼈대가 됩니다. 다음 단계를 활용하세요.

  1. 테이블 이름 정하기: 직관적으로 식별할 수 있는 테이블 이름을 입력합니다. 여기서는 "my_video_table"을 사용합니다. 이름 지정 시 하이픈(``)은 포함하지 않도록 주의하세요.

  2. API 요청 설정: 아래 코드를 사용해 업로드한 데이터 세트 경로에서 테이블 생성을 호출합니다. 이전 단계의 Dataset ID가 바르게 적용되어 있어야 합니다.

create_table_url = f"{base_api_url}/database/table/import/roe-dataset/"

table_name = "my_video_table"  # Replace with your desired table name

form_data = {
    "table_name": table_name,
    "dataset_id": f"{dataset_id}",
    "sync_dataset": "false",  # Set to "true" if you want to sync the dataset with the table
}

response = requests.post(create_table_url, headers=headers, data=form_data)

if response.status_code == 200:
    print("Success")
else:
    print("Failure!")
  1. 데이터 세트 동기화 옵션: sync_dataset 파라미터는 테이블 데이터를 실시간으로 데이터 세트 현황과 매칭시킬지 결정하는 플래그입니다. "true" 변경 시 원본 데이터 세트 변동 사항이 테이블 데이터에도 지속 반영됩니다. 편의상 이 튜토리얼은 "false"로 유지합니다.

  2. 코드 실행: 파이썬 상에서 코드를 동작시킵니다.

  3. 응답 확인: 테이블 구성이 완료되면 화면에 "Success"가 출력되고 실패 시 "Failure!"가 나타납니다.

  4. 트러블슈팅: 호출에 차질이 발생한다면 토큰 정보, Dataset ID, 계정의 테이블 생성 권한 등을 다시 한번 면밀히 체크하세요.

결과가 문제없다면 데이터 구조를 탐색하기 위해 컬럼을 확인해 볼 수 있습니다.

‍5단계: 사용 가능한 데이터 확인을 위해 테이블 컬럼 조회

테이블 내 속성들을 명확히 설계하고 검색 인덱스를 정밀 조준하기 위해서, 테이블에 어떤 컬럼이 포함되어 있는지 확인해야 합니다. 아래 단계를 시도하세요.

  1. API 요청 설정: 생성된 대상 테이블에서 컬럼을 가져오도록 아래 코드를 세ッティング합니다. 이전 단계의 정확한 테이블 이름이 매겨져야 타겟 컬럼 정보를 파악하기 원활합니다.

table_cols_url = f"{base_api_url}/database/table/{table_name}/columns"

response = requests.get(table_cols_url, headers=headers)

if response.status_code == 200:
    columns = response.json()  # Parsing the JSON response
    print("Success")
    print("Columns:", columns)
else:
    print("Failure! Status Code:", response.status_code)
  1. 코드 실행: 개발 창에서 파이썬 코드를 동작시킵니다.

  2. 응답 확인: 확인이 성공하면 "Success"와 함께 테이블 컬럼 데이터의 구조 목록이 출력됩니다. 실패하는 경우에는 현재 발생한 Status Code가 명시된 에러 로그 메시지가 출력됩니다.

  3. 트러블슈팅: 비정상 동작을 막으려면 다음 지표를 살펴보세요.

    • 사용하고 계신 API 토큰의 권한 만료 여부 및 인증 통과 여부를 검토합니다.

    • 조회 테이블명이 바로 직전에 생성했던 테이블 이름과 정확하게 호환되는지 대조합니다.

    • 만일 통신 오류 코드 401을 돌려받았다면 권한 인증 누락을 뜻하므로 토큰을 갱신해 보세요.

  4. 사용할 컬럼 식별: 정상 조회된 속성 데이터 배열 중 실질 비디오 정보 콘텐츠를 가리키고 있는 'files' 컬럼을 타겟으로 잡습니다. 매칭 대상 인덱스를 빌드하기 위해 아래 형태로 대상 어레이를 정의합니다.

# Assuming the columns are retrieved successfully
selected_columns = [columns[2]]  # Adjust the index based on the actual structure of the response

컬럼 정보를 무사히 취득했다면 뒤이어 테이블 상에서 시맨틱 검색 인덱스를 본격 생성할 단계로 나아갑니다.

6단계: Twelve Labs의 Marengo-2.6 비디오 임베딩 모델을 사용해 테이블 상의 검색 인덱스 생성

비디오 데이터를 영리하게 다룰 수 있는 고성능 검색 성능을 이식하기 위해, 먼저 Twelve Labs Marengo-2.6 임베딩 모델을 활용한 검색 인덱스를 구축해야 합니다. 각 데이터 유형에 최적화된 개별 임베딩 아키텍처가 활성화되도록 검색 인덱싱 스펙을 구성해 봅니다. 가이드는 다음과 같습니다.

  1. API 요청 설정: 아래 예시 코드를 실행해 검색 인덱스를 가동합니다. 직전 스크립트 블록에서 가져온 올바른 테이블 명칭과 세부 타겟 컬럼이 잘 전달되도록 준비하세요.

create_index_url = f"{base_api_url}/index/"
search_index_config = {
    "version": '1.0',
    "pdf": {
        "text_embedder_name": "jina-clip-v1",
        "image_embedder_name": "jina-clip-v1",
    },
    "text": {
        "embedder_name": "text-embedding-3-small",
    },
    "image": {
        "embedder_name": "jina-clip-v1",
    },
    "audio": {
        "embedder_name": 'None',
    },
    "video": {
        "embedder_name": "Marengo-retrieval-2.6",
    },
}

index_name = "my_search_index"  # Replace with your desired index name

form_data = {
    "name": index_name,
    "table_name": table_name,
    "id_column_name": "r_uuid",  # Replace with the actual ID column name if different
    "column_names": json.dumps(selected_columns),
    "search_index_config": json.dumps(search_index_config),
    "display_name": index_name,
}

response = requests.post(create_index_url, headers=headers, data=form_data)

if response.status_code == 201:
    print("Success")
else:
    print("Failure!")

index_id = response.json().get("id") if response.status_code == 201 else None
print(f"Index ID: {index_id}")
  1. 검색 인덱스 커스텀 셋업: 사전에 정의된 search_index_config 딕셔너리는 파일 유형에 매칭할 임베딩 엔진 스펙을 상세하게 기술한 객체입니다.

    • 텍스트(Text): 서술적 표현을 잘 파싱할 수 있게 "text-embedding-3-small"을 부착하여 대응합니다.

    • 비디오(Video): 풍부한 시네마틱 해석에 탁월한 "Marengo-retrieval-2.6" 엔진을 비디오 처리에 맞춤형으로 융합합니다. 해당 구조적 원리를 이해하고 싶다면 공식 스펙 시트를 참조하세요: https://docs.twelvelabs.io/docs/create-video-embeddings

    • PDF 및 이미지(Image): 대규모 이미지 인식에 검증된 멀티모달 모델 "jina-clip-v1"을 활용합니다.

    • 오디오(Audio): 이번 프로젝트 진행 영역에 포함되지 않으므로 'None'을 선언해 인덱싱 부하를 없앱니다. 오디오 임베딩이 작동하지 않아도 검색 기능에는 지장이 없습니다.

  2. 코드 작동: 파이썬 구동창에서 이 모듈을 가동합니다.

  3. 출력값 검증: 인덱싱 로직이 제대로 통과되면 화면상에 "Success"가 확인되며 실패 시 오류 구문과 실패 로그 코드가 발생합니다.

  4. 트러블슈팅 가이드: 비정상 에러 흐름을 통제하고 싶다면 다음 포인트를 리체크하세요.

    • 통신 요청에 탑재한 키 밸류의 옯고 그름 유무와 키 생성 시 인가된 스코프가 적당한지 재조회합니다.

    • 타겟 테이블과 선택한 컬럼 메타데이터 명칭이 단 한 글자의 오타 없이 매칭되어 있는지 더블 체크합니다.

    • 혹시 코드 201 이외의 응답이 반환되었다면 이는 전송 규정 누락을 가리키는 경우가 크므로 매뉴얼 서류 규칙과 포맷 요구사항을 검토해 주세요.

  5. 확보한 인덱스 ID: 정상적으로 빌드가 끝났다면 가동 창으로부터 생성된 Index ID 결과물이 노출되며, 향후 쿼리 실행 및 관련 데이터 세부 처리에서 메인 레퍼런스로 활용 가능합니다.

본 공정을 무사히 극복함으로써 고도로 연쇄 정렬된 Twelve Labs Marengo-2.6 엔진의 기능을 온전히 흡수시킬 수 있으며 정교한 시맨틱 비디오 질의 처리가 활성화됩니다.

7단계: 검색 인덱스 생성 상태 체크 및 대기 상태 확인

인덱스 빌드를 선언한 다음, 실시간 서버 내부에서 컴파일링 및 비디오 프레임 추출 처리가 안전히 마무리되기까지 일정 모니터링 주기가 수반되어야 합니다. 아래 단계를 따라 확인 프로세스를 수행하세요.

  1. API 요청 설정: 비디오 시퀀싱 데이터를 바쁘게 해독하고 있을 인덱서 엔진의 가도 완료 수준을 판정하기 위해 실시간 비동기 검사 스크립트를 구현합니다. 직전 스크립트에서 확인한 Index ID를 정확하게 할당해야 모니터링이 시작됩니다.

import time

check_status_url = f"{base_api_url}/index/{index_id}/status/"

max_retries = 120  # Maximum number of retries to check the status

# Start a loop to continuously check the status
for _ in range(max_retries):
    response = requests.get(check_status_url, headers=headers)

    if response.status_code == 200:
        status = response.json().get('status')

        # Check if the index creation is complete
        if status == 'SUCCESS':
            print("Index creation succeeded.")
            break
        elif status == 'FAILURE' or status == 'REVOKED':
            print("Index creation failed.")
            break

        print(f"Index status: {status}. Checking again in 10 seconds...")
        # Wait for 10 seconds before checking again
        time.sleep(10)
    else:
        print(f"Failed to get status: {response.status_code}")
        break
else:
    print("Max retries reached, exiting.")
  1. 실행 제어: 파이썬 테스트 도구 인프라에서 위의 지연 대기 연동 스크립트를 최종 가동합니다.

  2. 상태 모니터링: 코드 블록은 정상 프로세스가 종료될 때까지 최대 120회 간 주기를 갖고 10초 간격으로 서버 피드백 통신 로그를 수행하여 안정적인 대기 처리를 보장합니다.

  3. 리턴 값 판별:

    • 생성 상태가 SUCCESS 로 확인된다면 화면상에 "Index creation succeeded." 메시지가 프린팅되며 루프가 종료됩니다.

    • 시스템 비 정상 변수로 흐리멍덩한 루핑 실패나 FAILURE 혹은 REVOKED 꼬리가 출력될 때는 "Index creation failed." 실패 알람이 나타납니다.

    • 만일 현재 컴파일 중인 미완성 프로세스 진행 상황인 경우 현 상태 문자를 콘솔창에 찍어 현재 대기 상황 정보를 투명하게 갱신해 줍니다.

  4. 오류 확인 요령: 상태 확인 중 예상치 못한 버그를 마주했다면 하단 내역을 복기하세요.

    • 사용 토큰의 타겟 권한 지위가 이상 없는지, 계정 내 리소스 바인딩이 꼬이진 않았는지 살펴보세요.

    • 체크 중인 Index ID 대상 고유 키 값이 잘못 전달되지는 않았는지 검증합니다.

  5. 최대 반복 카운트 이탈: 만약 120번의 루프 완료까지 변동점이 없는 비정상 진행 상태가 방치될 때 툴에는 "Max retries reached, exiting."이 도출됩니다. 인코딩 스택 프로세싱 부하가 상상 이상으로 적체되어 있는 상태임을 예측해 볼 수 있습니다.

이로써 비디오 시맨틱 인덱스 구축 결과 안정성 진단을 깔끔하게 끝마쳤습니다. 대기열 확인이 정상 처리되었다면 다음 질의 파트로 당당히 넘어갈 준비가 모두 해결되었습니다.

8단계: 검색 목적과 입력 쿼리에 따른 정밀 비디오 자료 쿼리 검색 가동

드디어 비디오 컬렉션 탐색 인덱서 구조를 완성하고 완전한 검증을 넘었으니, 실사용 목적에 대응하는 테스트 쿼리를 던져 조건과 문장 상황에 맞춰 반응하는 고유 시맨틱 비디오를 찾아낼 순간입니다. 연산 질의 처리를 아래 형태로 개시해 보십시오.

  1. API 요청 설정: 아래 기술된 테스팅 질의용 스크립트 모듈을 준비하세요. 이전 검사를 끝낸 바로 그 활성화 완료 상태의 Index ID를 변수로 입력해 주셔야 작동합니다.

search_index_url = f"{base_api_url}/index/{index_id}/search/"

form_data = {
    "query": "tennis on grass",  # Replace with your search query
    "limit": "10"  # Optional: Limit the number of results returned
}

response = requests.post(search_index_url, headers=headers, data=form_data)

results = response.json().get("result_rows")

print("Videos from most to least relevant:\n")
for idx, result in enumerate(results):
    print(f"{idx + 1}: {result[1]}")
  1. 질의 커스텀하기: form_data 구문 속 정의된 "tennis on grass"(잔디밭 위 테니스) 대신, 상상 가능한 비디오 신 특징이나 씬 묘사를 영문 문자열 형태로 자유롭게 매핑해 보세요. 연동 결과 개수 제한을 걸고 싶다면 limit 파라미터를 적당한 정수 문자 값으로 조정해주면 제어됩니다.

  2. 실행 가동: 작성 도구 내에서 해당 파이썬 호출 인터페이스 코드를 동작하도록 구동합니다.

  3. 출력값 검증: 기동 시 시스템에 입력된 쿼리 질의 구조를 전달하여 결과 어레이를 끌어옵니다. 무사히 완수될 경우 일치율과 콘셉트 연관성에 따라 가깝게 매칭되는 비디오 순위를 가중치 순으로 바르게 노출해 줍니다.

  4. 결과값 판독 요령: 리턴된 개체 시퀀스는 순서별로 줄지어 나타나며, 시맨틱 문맥 매칭 상태가 높은 리소스 파일이 1번에서부터 표시됩니다. 현 구현 가이드는 결과 튜플의 후속 인자가 적정한 메타 속성 포맷(비디오 url 혹은 상세 타이틀)을 품고 있는 가정하에 설계되었습니다. 리스폰 구조가 상이한 구조인 경우 대상 인덱스 데이터 인덱싱 슬라이싱 변인을 다듬으십시오.

  5. 트러블슈팅 가이드: 만일 예측 외 난관에 부딪혔다면 다음 해결 실마리를 탐독하십시오.

    • 전송 타겟에 가미된 통신 토큰 권한 데이터 스펙에 이상 및 만료 상황이 없는지 실시간 확인하십시오.

    • 호출 대상으로 선택한 고유 활성화 Index ID 주소가 맞는지 조망하고 빌드 및 배포 완료 여부가 클린한지 살핍니다.

전과정을 성공적으로 완주함으로써 지능화된 Twelve Labs Embed API 구조를 Roe AI 데이터 전처리 체계에 멋지게 융합하여 인위적인 태깅 과정 없이 고퀄리티 시맨틱 탐색 서비스를 작동시키는 신세계를 맞이하게 되었습니다.

결론

본 가이드에서는 Twelve Labs의 비디오 임베딩 능력과 Roe AI의 데이터 관리 능력을 밀착 가동하여, 비디오 시각 정보의 함의와 복합 정황을 맥락대로 추출하여 질의에 맞춤 응답하는 지능형 검색 프레임워크를 개발하는 핵심 공정을 설명했습니다. 이 단계를 충실히 완수한 개발자라면 차세대 기술 트렌드로 자리 매김할 의미 기반 멀티모달 서비스 구성의 강력한 응용 기초를 확보하게 된 셈입니다.

개발자에게 있어 이번 두 기술 플랫폼의 유기적인 만남은 미래형 비디오 컴퓨팅 구축을 가속하는 시발점이 되어 줍니다. Twelve Labs가 품은 디테일한 비디오 영상 맥락 인지 신경망 알고리즘과 Roe AI가 조율하는 유동적인 관계형 데이터 관리 메커니즘을 융합함으로써, 상상에 그쳤던 상황 주도형 멀티모달 솔루션을 매우 수월하고 기민하게 제작할 수 있게 되었습니다.

여기서 그치지 말고, 이 유연한 구조를 어떻게 본인 고유의 실무 시나리오에 응용하고 변용할지 상상력을 확장해 보세요. 사용자의 활동 및 시청 로그에 긴밀히 반응하는 유동형 미디어 추천 시스템, 대용량 아카이브를 자율 수집 및 가이드 진단하는 비디오 인텔리전스 레이블 생성 파이프라인 등, 이번 시너지는 풍요로운 멀티미디어 도메인의 도약에 훌륭하고 주춧돌 같은 디딤돌 역할을 지원해 줄 것입니다.

부록

학습과 개발 과정에서 언제든 활용할 수 있는 추가적인 리소스입니다.

  1. 전과정 동작 코드가 망라된 Colab 노트북

  2. Twelve Labs 공식 API 문서

  3. Roe AI 개발 가이드 서재

여러분이 이번 튜토리얼을 통해 어떤 혁신적인 서비스를 만들어낼지 무척 기대됩니다. 멋진 아이디어와 멋진 작품들을 Twelve Labs와 Roe AI 커뮤니티에 적극 공유해 주세요. 즐거운 개발 되시길 바랍니다!