영상으로 3D 모델 만들기

3d오픈소스모델TypescriptPython
avatar
2025.04.22
·
4 min read

순서

  1. 영상 촬영 후 영상을 각 프레임 단위로 스크린샷 (이미지 생성)

  2. 이미지를 활용하여 3D 모델 생성 (USDZ 파일)

  3. USDZ파일 > GLB 파일 변환

  4. GLB 파일 웹에서 확인


환경

  • 운영체제 : MacOS (M1)

  • 서버 : NodeJS

  • 클라이언트 : React (Web)


영상 촬영 후 영상을 각 프레임 단위로 스크린샷 (이미지 생성)

사전에 영상 준비 (.mp4 또는 .avi 또는 .mov 파일)

모듈 준비 (fluent-ffmpeg, ffmpeg-static)

yarn add fluent-ffmpeg ffmpeg-static

코드 작성

import * as ffmpeg from 'fluent-ffmpeg';
import * as ffmpegStatic from 'ffmpeg-static';

if (!ffmpegStatic) throw new Error('ffmpeg-static 경로를 찾을 수 없습니다.');
ffmpeg.setFfmpegPath(ffmpegStatic as unknown as string);

const videoToPicture = async (
  inputVideoPath: string,
  outputFolderName: string,
  callback: () => void | Promise<void>,
): Promise<void> => {
  ffmpeg(inputVideoPath)
    .on('error', () => {})
    .on('end', () => callback())
    .screenshots({
      count: 100,
      folder: outputFolderName,
      filename: 'input-%03d.png',
    });
};

videoToPicture(영상경로, 이미지저장경로, () => {
  // callback function
});

이미지를 활용하여 3D 모델 생성 (USDZ 파일)

Apple Open Source 사용 (Creating a Photogrammetry Command-Line App)

DownloadXCode에서 Archive 후 실행파일 생성

CLI 명령어를 사용하여 코드 작성

이미지 > 3D 모델 (USDZ 파일)

import { execSync } from 'child_process';

// ~/HelloPhotogrammetry <이미지경로> <결과저장경로>/output.usdz -d raw -o sequential -f normal
let command = __dirname + '/../../../HelloPhotogrammetry "';
command += inputFolderPath + '" "';
command += outputFilePath + '.usdz" ';
command += '-d raw -o sequential -f normal';

execSync(command, { stdio: 'inherit' });

3D 모델 (USDZ 파일) > 3D 모델 (GLB 파일) 의 파일 변환 프로그램 설치 (Blender)

Download 후 터미널에서 설치 확인 테스트

blender --version
# Blender 4.4.1
# 	build date: 2025-04-15
#	build time: 01:30:48
#   ...

파일 변환 스크립트 작성

import bpy
import sys

# Node.js에서 전달된 인자 받아오기
input_path = sys.argv[-2]
output_path = sys.argv[-1]

# 초기화
bpy.ops.wm.read_homefile(use_empty=True)

# USDZ 불러오기
bpy.ops.wm.usd_import(filepath=input_path)

# glb로 내보내기
bpy.ops.export_scene.gltf(
    filepath=output_path,
    export_format='GLB',
    export_apply=True
)

CLI 명령어를 사용하여 코드 작성

3D 모델 (USDZ 파일) > 3D 모델 (GLB 파일)

import { execSync } from 'child_process';

// ~/blender --background --python convert_usdz_to_glb.py -- input.usdz output.glb
const inputPath = outputFilePath + '.usdz';
const outputPath = outputFilePath + '.glb';
const blenderScript = 'convert_usdz_to_glb.py';
let command = 'blender --background --python ';
command += blenderScript + ' -- ' + inputPath + ' ' + outputPath;

execSync(command, { stdio: 'inherit' });

GLB 파일 웹에서 확인

모듈 준비

yarn add @google/model-viewer

코드 작성

import "@google/model-viewer";

interface Props {
  src: string;
  iosSrc: string;
  poster: string;
}

export default ({ src, iosSrc, poster }: Props) => {
  return (
    <model-viewer
      src={src}
      ios-src={iosSrc}
      poster={poster}
      alt="3D 모델 미리보기"
      auto-rotate
      camera-controls
      ar
      ar-modes="webxr scene-viewer quick-look"
      touch-action="pan-y"
      intensity="1"
      style={{ width: "100%", height: "100%" }}
    />
  );
};