Chào bạn! Mình là Minh, một developer đã dành hơn 3 năm làm việc với các giải pháp AI xử lý video. Hôm nay, mình sẽ chia sẻ chi tiết nhất có thể về cách tích hợp AI Video Summary API và trích xuất key frame từ video — dành cho những bạn mới bắt đầu hoàn toàn không có kinh nghiệm về API.

Qua bài viết này, bạn sẽ hiểu cách hoạt động của video summary API, cách trích xuất các khung hình quan trọng (key frame), và cách triển khai vào dự án thực tế. Mình đã thử nghiệm với nhiều nhà cung cấp và HolySheep AI thực sự là lựa chọn tối ưu về chi phí và tốc độ.

Mục Lục

1. Giới Thiệu Tổng Quan Về AI Video Summary

AI Video Summary là công nghệ sử dụng trí tuệ nhân tạo để phân tích nội dung video và tạo ra bản tóm tắt tự động. Thay vì xem toàn bộ video 2 tiếng, bạn chỉ cần đọc bản tóm tắt 5 phút hoặc xem 10 key frame đại diện.

Trong thực tế, mình đã áp dụng công nghệ này cho:

2. API Là Gì? Giải Thích Đơn Giản

Nếu bạn chưa biết, API (Application Programming Interface) là cách để các phần mềm "nói chuyện" với nhau. Hãy tưởng tượng như ordering food qua Grab:

Bạn không cần biết Grab nấu ăn thế nào, chỉ cần gọi API và nhận kết quả. Đơn giản vậy!

3. Key Frame Là Gì?

Key Frame (khung hình chính) là những khung hình quan trọng nhất trong video — thể hiện nội dung cốt lõi, thay đổi cảnh, hoặc thông tin quan trọng.

Ví dụ thực tế:

4. Thiết Lập Môi Trường & Lấy API Key

4.1 Đăng ký tài khoản HolySheep AI

Đầu tiên, bạn cần tạo tài khoản tại HolySheep AI. HolySheep cung cấp:

4.2 Cài đặt Python (nếu chưa có)

# Windows: Tải Python từ python.org

macOS: brew install python3

Linux: sudo apt install python3 python3-pip

Kiểm tra cài đặt

python3 --version pip3 --version

4.3 Cài đặt thư viện cần thiết

# Cài đặt các thư viện cần thiết
pip3 install requests pillow moviepy opencv-python

Kiểm tra cài đặt thành công

python3 -c "import requests; print('Requests OK')"

5. Tích Hợp API Bằng Python

Đây là phần quan trọng nhất! Mình sẽ hướng dẫn từng bước với code mẫu có thể chạy ngay.

5.1 Code cơ bản - Gửi video và nhận Summary

import requests
import json
import base64
import time

Cấu hình API

BASE_URL = "https://api.holysheep.ai/v1" API_KEY = "YOUR_HOLYSHEEP_API_KEY" # Thay bằng key của bạn def get_video_summary(video_path): """ Gửi video lên API và nhận bản tóm tắt """ headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } # Đọc video và chuyển thành base64 with open(video_path, "rb") as video_file: video_data = base64.b64encode(video_file.read()).decode('utf-8') payload = { "model": "video-summary-v2", "video_data": video_data, "options": { "max_frames": 15, # Số key frame tối đa "summary_length": "medium", # short/medium/long "include_timestamps": True } } start_time = time.time() response = requests.post( f"{BASE_URL}/video/summary", headers=headers, json=payload, timeout=120 ) latency = (time.time() - start_time) * 1000 if response.status_code == 200: result = response.json() print(f"✅ Xử lý hoàn tất trong {latency:.2f}ms") return result else: print(f"❌ Lỗi {response.status_code}: {response.text}") return None

Sử dụng

result = get_video_summary("sample_video.mp4") if result: print("Summary:", result.get("summary")) print("Key Frames:", result.get("keyframes"))

5.2 Code nâng cao - Xử lý video dài với chunking

import requests
import base64
import os
from concurrent.futures import ThreadPoolExecutor

BASE_URL = "https://api.holysheep.ai/v1"
API_KEY = "YOUR_HOLYSHEEP_API_KEY"

def process_video_chunk(chunk_path, chunk_index):
    """
    Xử lý từng phần của video
    """
    headers = {"Authorization": f"Bearer {API_KEY}"}
    
    with open(chunk_path, "rb") as f:
        chunk_data = base64.b64encode(f.read()).decode('utf-8')
    
    payload = {
        "model": "video-summary-v2",
        "video_data": chunk_data,
        "chunk_index": chunk_index,
        "options": {
            "max_frames": 10,
            "summary_length": "short"
        }
    }
    
    response = requests.post(
        f"{BASE_URL}/video/summary/chunk",
        headers=headers,
        json=payload,
        timeout=180
    )
    
    return response.json() if response.status_code == 200 else None

def merge_results(chunk_results):
    """
    Gộp kết quả từ các chunk
    """
    merged = {
        "summary": "",
        "keyframes": [],
        "timeline": []
    }
    
    for result in chunk_results:
        if result:
            merged["summary"] += result.get("summary", "") + "\n"
            merged["keyframes"].extend(result.get("keyframes", []))
            merged["timeline"].extend(result.get("timeline", []))
    
    return merged

def process_long_video(video_path, num_chunks=4):
    """
    Xử lý video dài bằng cách chia thành nhiều phần
    """
    # Code chia video (sử dụng ffmpeg)
    chunk_dir = "temp_chunks"
    os.makedirs(chunk_dir, exist_ok=True)
    
    # Chia video thành các phần bằng nhau
    for i in range(num_chunks):
        start_time = i * 15  # Mỗi phần 15 phút
        chunk_path = f"{chunk_dir}/chunk_{i}.mp4"
        
        os.system(f'ffmpeg -i "{video_path}" -ss {start_time} '
                  f'-t 900 -c copy "{chunk_path}" -y')
    
    # Xử lý song song các chunk
    with ThreadPoolExecutor(max_workers=4) as executor:
        futures = [
            executor.submit(process_video_chunk, f"{chunk_dir}/chunk_{i}.mp4", i)
            for i in range(num_chunks)
        ]
        chunk_results = [f.result() for f in futures]
    
    # Gộp kết quả
    final_result = merge_results(chunk_results)
    
    # Dọn dẹp
    for i in range(num_chunks):
        os.remove(f"{chunk_dir}/chunk_{i}.mp4")
    
    return final_result

Sử dụng cho video 60 phút

result = process_long_video("long_lecture.mp4", num_chunks=4) print(f"Tổng key frames: {len(result['keyframes'])}")

6. Tích Hợp API Bằng Node.js

Nếu bạn quen thuộc với JavaScript/Node.js, đây là cách tích hợp:

const axios = require('axios');
const fs = require('fs');
const path = require('path');

const BASE_URL = 'https://api.holysheep.ai/v1';
const API_KEY = 'YOUR_HOLYSHEEP_API_KEY';

class VideoSummaryAPI {
    constructor(apiKey) {
        this.client = axios.create({
            baseURL: BASE_URL,
            headers: {
                'Authorization': Bearer ${apiKey},
                'Content-Type': 'application/json'
            },
            timeout: 120000
        });
    }

    async getSummary(videoPath, options = {}) {
        // Đọc video và chuyển thành base64
        const videoBuffer = fs.readFileSync(videoPath);
        const videoBase64 = videoBuffer.toString('base64');
        
        const startTime = Date.now();
        
        try {
            const response = await this.client.post('/video/summary', {
                model: 'video-summary-v2',
                video_data: videoBase64,
                options: {
                    max_frames: options.maxFrames || 15,
                    summary_length: options.summaryLength || 'medium',
                    include_timestamps: true
                }
            });
            
            const latency = Date.now() - startTime;
            console.log(✅ Xử lý hoàn tất trong ${latency}ms);
            
            return {
                success: true,
                data: response.data,
                latency
            };
        } catch (error) {
            console.error('❌ Lỗi API:', error.message);
            return {
                success: false,
                error: error.message,
                status: error.response?.status
            };
        }
    }

    async getKeyFrames(videoPath, maxFrames = 20) {
        const result = await this.getSummary(videoPath, {
            maxFrames,
            summaryLength: 'short'
        });
        
        if (result.success) {
            return {
                frames: result.data.keyframes || [],
                timestamps: result.data.timestamps || []
            };
        }
        return null;
    }
}

// Sử dụng
const api = new VideoSummaryAPI(API_KEY);

async function main() {
    const result = await api.getSummary('./sample_video.mp4', {
        maxFrames: 15,
        summaryLength: 'medium'
    });
    
    if (result.success) {
        console.log('Summary:', result.data.summary);
        console.log('Key Frames Count:', result.data.keyframes?.length);
    }
}

main().catch(console.error);

7. Quy Trình Xử Lý Video Từ A Đến Z

Dựa trên kinh nghiệm thực chiến, đây là quy trình mình áp dụng cho các dự án:

Bước 1: Chuẩn bị video

import cv2

def prepare_video(input_path, output_path, max_duration=600):
    """
    Chuẩn bị video: resize, cắt nếu quá dài, chuẩn hóa format
    """
    cap = cv2.VideoCapture(input_path)
    
    # Lấy thông tin video
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    duration = total_frames / fps
    
    print(f"Video info: {width}x{height}, {fps}fps, {duration:.1f}s")
    
    # Nếu video quá dài, cắt
    if duration > max_duration:
        print(f"Cắt video từ {duration:.1f}s xuống {max_duration}s")
        # Sử dụng ffmpeg để cắt
        os.system(f'ffmpeg -i "{input_path}" -t {max_duration} '
                  f'-c copy "{output_path}" -y')
    else:
        os.system(f'cp "{input_path}" "{output_path}"')
    
    cap.release()
    return output_path

Chuẩn bị trước khi gửi API

prepared_video = prepare_video("raw_video.avi", "processed_video.mp4")

Bước 2: Gọi API và xử lý response

import json
from datetime import datetime

def save_keyframes(keyframes_data, output_dir="keyframes"):
    """
    Lưu các key frames xuống thư mục
    """
    os.makedirs(output_dir, exist_ok=True)
    saved_paths = []
    
    for i, frame_data in enumerate(keyframes_data):
        # frame_data chứa base64 image
        timestamp = frame_data.get('timestamp', i)
        image_data = base64.b64decode(frame_data['image_base64'])
        
        filename = f"{output_dir}/frame_{i:03d}_{timestamp:.1f}s.jpg"
        with open(filename, 'wb') as f:
            f.write(image_data)
        
        saved_paths.append({
            'filename': filename,
            'timestamp': timestamp,
            'scene': frame_data.get('scene_description', '')
        })
    
    # Lưu metadata
    with open(f"{output_dir}/metadata.json", 'w') as f:
        json.dump(saved_paths, f, indent=2)
    
    return saved_paths

def create_video_timeline(keyframes, summary):
    """
    Tạo timeline video từ key frames
    """
    timeline = {
        'video_summary': summary,
        'segments': []
    }
    
    prev_time = 0
    for i, frame in enumerate(keyframes):
        segment = {
            'index': i,
            'start_time': prev_time,
            'end_time': frame.get('timestamp', prev_time + 5),
            'description': frame.get('scene', ''),
            'thumbnail': frame.get('thumbnail_path', '')
        }
        timeline['segments'].append(segment)
        prev_time = segment['end_time']
    
    return timeline

Sử dụng

result = get_video_summary("processed_video.mp4") if result: saved_frames = save_keyframes(result['keyframes']) timeline = create_video_timeline(result['keyframes'], result['summary']) # Lưu timeline with open("video_timeline.json", 'w') as f: json.dump(timeline, f, ensure_ascii=False, indent=2)

8. Tối Ưu Hóa Quá Trình Xử Lý

8.1 So sánh chi phí các nhà cung cấp (2026)

Nhà cung cấpGiá/MTokTỷ lệ tiết kiệm
GPT-4.1$8.00Tham chiếu
Claude Sonnet 4.5$15.00Chi phí cao