# APNG Lip Sync Tool 개발기 - v2: Gemini API 연동 테스트 ## 개요 v1에서 프로젝트 구조를 설계했습니다. 이번 v2에서는 **Gemini API**와의 연동을 테스트합니다. 특히 두 가지 핵심 기능을 검증합니다: 1. **이미지 분석**: 업로드된 얼굴 이미지의 특성 파악 2. **이미지 생성 (Nano Banana)**: 원본을 기반으로 입모양 변형 이미지 생성 ## Gemini API 클라이언트 구현 ```python # src/gemini_client.py from google import genai from google.genai import types def get_client(): """Get Gemini client instance.""" return genai.Client(api_key=GOOGLE_API_KEY) def analyze_face_image(image_path: str | Path) -> dict: """Analyze a face image to extract features.""" client = get_client() with open(image_path, "rb") as f: image_data = f.read() image_part = types.Part.from_bytes( data=image_data, mime_type=f"image/{image_path.suffix[1:].lower()}" ) prompt = """Analyze this face image for lip sync animation... 1. Face position and angle 2. Mouth region location and shape 3. Art style 4. Skin tone and lip color 5. Distinctive features around the mouth""" response = client.models.generate_content( model=GEMINI_MODEL, contents=[prompt, image_part] ) return {"analysis": response.text, "image_path": str(image_path)} ``` ## 테스트용 이미지 생성 실제 인물 사진 대신 간단한 카툰 얼굴을 Pillow로 생성하여 테스트했습니다: ```python from PIL import Image, ImageDraw def create_test_face_image(output_path): img = Image.new('RGB', (400, 400), color='#FFE4C4') draw = ImageDraw.Draw(img) # Face, eyes, nose, mouth... draw.ellipse([50, 50, 350, 350], fill='#FFDAB9') draw.arc([140, 240, 260, 310], 0, 180, fill='#CD5C5C', width=4) # ... img.save(output_path) ``` ## 이미지 분석 결과 생성된 테스트 이미지로 Gemini 분석을 수행한 결과: ``` Face Position: Frontal view Mouth Shape: Arc-shaped line representing a closed smile Art Style: Simplified cartoon style Skin Tone: Light peach Lip Color: Light reddish-pink/magenta ``` Gemini는 이미지의 스타일과 입 위치를 정확히 파악했습니다. ## Viseme 이미지 생성 (Nano Banana) 가장 중요한 기능인 입모양 변형 테스트: ```python def generate_viseme_image(original_image_path, viseme, viseme_description, output_path): """Generate a viseme variation of the original image.""" client = get_client() prompt = f"""Edit this face image to change ONLY the mouth shape. Target: {viseme} - {viseme_description} Keep all other features exactly the same.""" response = client.models.generate_content( model=GEMINI_IMAGE_MODEL, contents=[prompt, image_part], config=types.GenerateContentConfig( response_modalities=["IMAGE", "TEXT"] ) ) # Extract and save generated image for part in response.candidates[0].content.parts: if part.inline_data and part.inline_data.mime_type.startswith("image/"): with open(output_path, "wb") as f: f.write(part.inline_data.data) ``` **결과**: ✓ Viseme 'A' (입 벌린 모양) 생성 성공! ## 테스트 결과 요약 | 테스트 | 결과 | |--------|------| | API 연결 | ✓ 성공 | | 이미지 분석 | ✓ 성공 | | Viseme 생성 | ✓ 성공 | ## 발견한 점 1. **Gemini 2.0 Flash**는 이미지 분석과 생성을 모두 지원 2. `response_modalities=["IMAGE", "TEXT"]` 설정으로 이미지 출력 가능 3. 간단한 카툰 스타일에서 입모양 변형이 잘 작동함 ## 다음 단계 (v3) v3에서는 실제 PHP 인터페이스를 통한 이미지 업로드 기능을 완성하고, 업로드된 이미지로 분석 API를 호출하는 전체 흐름을 구현합니다. --- *이 시리즈는 총 16개의 포스트로 구성되어 있습니다.*