Pemahaman Video dalam Agen
Ekstraksi bingkai, peringkasan video, dan penalaran temporal pada klip.
Pemahaman Video dalam Agen adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.
Pemahaman Video untuk Agen
Sebagian besar LLM tidak dapat memproses berkas video secara langsung, tetapi agen dapat menganalisis video dengan mengekstrak bingkai yang representatif dan mengirimkannya sebagai gambar. Agen kemudian melakukan penalaran terhadap urutan visual tersebut untuk mendeteksi peristiwa, perubahan, dan pola dari waktu ke waktu.
Memasang OpenCV untuk Ekstraksi Bingkai
OpenCV (cv2) adalah pustaka standar untuk pemrosesan video dalam Python. Pustaka ini memungkinkan Anda membuka berkas video, membaca metadatanya (laju bingkai, resolusi, jumlah bingkai), dan mengekstrak setiap bingkai sebagai larik NumPy.
# pip install opencv-python-headless
import cv2
def get_video_metadata(video_path: str) -> dict:
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
raise IOError(f'Cannot open video: {video_path}')
fps = cap.get(cv2.CAP_PROP_FPS)
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
duration_s = frame_count / fps if fps > 0 else 0
cap.release()
return {
'fps': round(fps, 2),
'frame_count': frame_count,
'width': width,
'height': height,
'duration_seconds': round(duration_s, 2)
}
meta = get_video_metadata('recording.mp4')
print(meta)Mengekstrak Bingkai Setiap N Detik
Untuk sebagian besar tugas pemahaman video, Anda tidak memerlukan setiap bingkai. Mengambil sampel satu bingkai setiap N detik memberikan ringkasan yang representatif tentang isi video. Pada laju 1 bingkai per detik, video berdurasi 60 detik menghasilkan 60 bingkai.
import cv2
import os
def extract_frames(
video_path: str,
output_dir: str,
every_n_seconds: float = 5.0
) -> list:
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
frame_interval = int(fps * every_n_seconds)
os.makedirs(output_dir, exist_ok=True)
saved_frames = []
frame_idx = 0
while True:
ret, frame = cap.read()
if not ret:
break
if frame_idx % frame_interval == 0:
timestamp = round(frame_idx / fps, 2)
fname = f'{output_dir}/frame_{frame_idx:06d}_{timestamp}s.jpg'
cv2.imwrite(fname, frame)
saved_frames.append({'path': fname, 'timestamp': timestamp})
frame_idx += 1
cap.release()
print(f'Extracted {len(saved_frames)} frames')
return saved_framesDeteksi Perubahan Adegan
Alih-alih mengambil sampel secara seragam, ekstrak bingkai pada batas adegan — momen ketika isi visual berubah secara signifikan. Cara ini menghasilkan bingkai yang lebih informatif untuk setiap panggilan API. Gunakan perbandingan selisih bingkai: jika perbedaan absolut rata-rata antara bingkai yang berurutan melebihi ambang batas, berarti terjadi perubahan adegan.
import cv2
import numpy as np
def extract_scene_change_frames(
video_path: str,
output_dir: str,
diff_threshold: float = 30.0
) -> list:
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
os.makedirs(output_dir, exist_ok=True)
prev_gray = None
saved = []
frame_idx = 0
while True:
ret, frame = cap.read()
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
if prev_gray is not None:
diff = np.mean(np.abs(gray.astype(float) - prev_gray.astype(float)))
if diff > diff_threshold:
ts = round(frame_idx / fps, 2)
fname = f'{output_dir}/scene_{frame_idx:06d}_{ts}s.jpg'
cv2.imwrite(fname, frame)
saved.append({'path': fname, 'timestamp': ts, 'diff': round(diff, 2)})
prev_gray = gray
frame_idx += 1
cap.release()
return savedMengirim Urutan Bingkai ke API Visi
Kirim beberapa bingkai yang diekstrak ke API visi dalam satu pesan. Sertakan stempel waktu setiap bingkai agar model dapat menalar urutan waktu dan durasinya. Minta secara eksplisit penalaran temporal dalam instruksi Anda.
import base64
import anthropic
def describe_video_frames(frame_info_list: list, query: str) -> str:
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
content = []
for fi in frame_info_list:
with open(fi['path'], 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
content.append({
'type': 'text',
'text': f'Frame at {fi["timestamp"]}s:'
})
content.append({
'type': 'image',
'source': {'type': 'base64', 'media_type': 'image/jpeg', 'data': b64}
})
content.append({'type': 'text', 'text': query})
response = client.messages.create(
model='claude-opus-4-5',
max_tokens=1024,
messages=[{'role': 'user', 'content': content}]
)
return response.content[0].textInstruksi Penalaran Temporal
Penalaran temporal memerlukan perumusan instruksi yang spesifik. Minta model membandingkan bingkai secara eksplisit, mencatat perubahan, memperkirakan durasi aktivitas, dan mengidentifikasi hubungan sebab-akibat antarb bingkai.
TEMPORAL_QUERY = (
'You are analysing a video sequence. The frames above are in chronological order '
'with their timestamps shown. Please:\n'
'1. Describe what changed between the first and last frame\n'
'2. Identify any notable events and when they occurred (timestamp)\n'
'3. Summarise the overall activity shown in the video\n'
'4. Estimate the total duration of the main activity\n'
'Be specific about timestamps.'
)
# More targeted temporal query:
CHANGE_DETECTION_QUERY = (
'Compare frame at {start_ts}s and frame at {end_ts}s. '
'List all visible differences in bullet points. '
'Categorise each change as: object_moved, object_added, '
'object_removed, lighting_change, or camera_move.'
)
# Usage:
query = CHANGE_DETECTION_QUERY.format(start_ts=0.0, end_ts=20.0)
if __name__ == '__main__':
print('Temporal reasoning query:')
print(TEMPORAL_QUERY)
print()
print('Change detection query:')
print(query)
Alur Pemrosesan Ringkasan Video
Alur pemrosesan ringkasan video yang lengkap: ekstrak bingkai → kirim ke model visi dalam beberapa kelompok → kumpulkan ringkasan setiap kelompok → susun ringkasan akhir. Pengelompokan mencegah terlampauinya batas jendela konteks.
def summarise_video(
video_path: str,
every_n_seconds: float = 10.0,
batch_size: int = 5
) -> str:
import anthropic
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
# Extract frames
frames = extract_frames(video_path, '/tmp/video_frames', every_n_seconds)
# Process in batches
batch_summaries = []
for i in range(0, len(frames), batch_size):
batch = frames[i:i + batch_size]
ts_range = f'{batch[0]["timestamp"]}s - {batch[-1]["timestamp"]}s'
query = f'Summarise what happens in this video segment ({ts_range}).'
summary = describe_video_frames(batch, query)
batch_summaries.append(f'[{ts_range}] {summary}')
# Synthesise
all_summaries = '\n\n'.join(batch_summaries)
result = client.messages.create(
model='claude-opus-4-5',
max_tokens=512,
messages=[{'role': 'user', 'content':
f'Here are segment-level video summaries:\n\n{all_summaries}\n\n'
'Write a single coherent summary of the entire video.'
}]
)
return result.content[0].textMelacak Objek Antarbingkai
Minta model visi melacak objek tertentu di seluruh urutan bingkai. Contohnya: 'Pada setiap bingkai, jelaskan posisi mobil merah: kiri atas, kanan atas, tengah, kiri bawah, kanan bawah.' Cara ini membuat lintasan gerak kasar tanpa algoritme pelacakan visi komputer.
def track_object_across_frames(
frames: list,
object_description: str
) -> list:
import anthropic, base64
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
trajectory = []
for fi in frames:
with open(fi['path'], 'rb') as f:
b64 = base64.standard_b64encode(f.read()).decode('utf-8')
response = client.messages.create(
model='claude-opus-4-5',
max_tokens=128,
messages=[{
'role': 'user',
'content': [
{'type': 'image', 'source': {'type': 'base64',
'media_type': 'image/jpeg', 'data': b64}},
{'type': 'text', 'text':
f'Where is the {object_description} in this frame? '
'Answer with one of: top-left, top-right, centre, '
'bottom-left, bottom-right, not-visible.'}
]
}]
)
trajectory.append({
'timestamp': fi['timestamp'],
'position': response.content[0].text.strip()
})
return trajectoryMenangani Batas Jumlah Bingkai
Jendela konteks API visi memiliki batas jumlah gambar yang dapat dikirim dalam satu permintaan (biasanya 5–20 gambar). Untuk video panjang, gunakan pendekatan hierarkis: analisis setiap segmen secara terpisah, lalu gabungkan ringkasan segmen menjadi ringkasan akhir menggunakan panggilan LLM kedua.
MAX_FRAMES_PER_REQUEST = 8
def hierarchical_video_analysis(frames: list, final_query: str) -> str:
import anthropic
client = anthropic.Anthropic(api_key='YOUR_API_KEY')
# Level 1: analyse each chunk
chunk_summaries = []
for i in range(0, len(frames), MAX_FRAMES_PER_REQUEST):
chunk = frames[i:i + MAX_FRAMES_PER_REQUEST]
ts = f'{chunk[0]["timestamp"]}s-{chunk[-1]["timestamp"]}s'
summary = describe_video_frames(
chunk, f'What happens in this segment ({ts})?'
)
chunk_summaries.append(f'Segment {ts}: {summary}')
# Level 2: synthesise all chunk summaries
combined = '\n'.join(chunk_summaries)
result = client.messages.create(
model='claude-opus-4-5',
max_tokens=512,
messages=[{
'role': 'user',
'content': f'Video segments:\n{combined}\n\n{final_query}'
}]
)
return result.content[0].textMenggabungkan Analisis Audio dan Video
Untuk pemahaman yang paling menyeluruh, gabungkan analisis visual tingkat bingkai dengan transkripsi audio Whisper. Agen dapat menghubungkan apa yang dilihat dengan apa yang dikatakan pada setiap stempel waktu, sehingga memungkinkan tugas yang bermanfaat seperti analisis rapat atau pengindeksan tutorial.
def full_video_analysis(video_path: str) -> dict:
import subprocess
# Step 1: Extract audio track
audio_path = '/tmp/video_audio.mp3'
subprocess.run([
'ffmpeg', '-i', video_path, '-q:a', '0', '-map', 'a',
audio_path, '-y'
], capture_output=True)
# Step 2: Transcribe audio
transcript_data = transcribe_with_timestamps(audio_path)
# Step 3: Extract key frames
frames = extract_frames(video_path, '/tmp/key_frames', every_n_seconds=15.0)
# Step 4: Visual summary
visual_summary = hierarchical_video_analysis(
frames, 'Summarise the visual content.'
)
return {
'transcript': transcript_data['full_text'],
'transcript_segments': transcript_data['segments'],
'visual_summary': visual_summary,
'frame_count': len(frames)
}Pembersihan dan Pengelolaan Bingkai
Bingkai yang diekstrak dapat cepat menumpuk. Selalu bersihkan berkas bingkai sementara setelah pemrosesan, dan terapkan tembolok bingkai dengan kunci berdasarkan nilai pencincangan dari (jalur video, laju bingkai) untuk menghindari ekstraksi ulang saat video yang sama dianalisis berulang kali.
import os
import shutil
import hashlib
FRAME_CACHE_DIR = '/tmp/frame_cache'
def get_cache_key(video_path: str, every_n_seconds: float) -> str:
content = f'{video_path}:{every_n_seconds}'
return hashlib.md5(content.encode()).hexdigest()[:12]
def get_or_extract_frames(video_path: str, every_n_seconds: float) -> list:
key = get_cache_key(video_path, every_n_seconds)
cache_dir = os.path.join(FRAME_CACHE_DIR, key)
if os.path.exists(cache_dir):
print(f'Cache hit: {key}')
files = sorted(os.listdir(cache_dir))
return [
{'path': os.path.join(cache_dir, f),
'timestamp': float(f.split('_')[-1].replace('s.jpg', ''))}
for f in files if f.endswith('.jpg')
]
return extract_frames(video_path, cache_dir, every_n_seconds)
def clear_frame_cache():
if os.path.exists(FRAME_CACHE_DIR):
shutil.rmtree(FRAME_CACHE_DIR)
print('Frame cache cleared')Uji Pemahaman
Mengapa deteksi perubahan adegan lebih baik daripada pengambilan sampel bingkai secara seragam untuk analisis video?
Ringkasan: Pemahaman Video dalam Agen
Kerja bagus! Poin-poin penting dari pelajaran ini:
- OpenCV: ekstrak bingkai dengan
cap.read(); ambil sampel setiap N detik atau saat terjadi perubahan adegan - Urutan bingkai: kirim dalam urutan kronologis dengan stempel waktu untuk memberikan konteks temporal
- Analisis hierarkis: bagi menjadi beberapa kelompok → ringkasan segmen → sintesis akhir
- Analisis gabungan: ffmpeg mengekstrak audio; Whisper mentranskripsikannya; lakukan rujuk silang dengan bingkai visual
- Tembolok bingkai: hindari ekstraksi berulang dengan direktori tembolok yang menggunakan kunci hash
Berikutnya: penalaran lintas modalitas — ketika teks menyatakan satu hal, tetapi gambar menunjukkan hal lain.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Pemahaman Video dalam Agen” gratis?
Ya — teks lengkap “Pemahaman Video dalam Agen” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Pemahaman Video dalam Agen”?
Ekstraksi bingkai, peringkasan video, dan penalaran temporal pada klip. Kamu berlatih AI Agents dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai AI Agents?
Tidak diperlukan pengalaman sebelumnya. AI Agents di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “Pemahaman Video dalam Agen” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Agents ini?
Ya. Setiap pelajaran AI Agents menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Agen Gambar + Teks dengan Claude Vision dan GPT-4V
- Alur Kerja Agen Audio + Teks
- Pemahaman Video dalam Agen
- Pola Penalaran Lintas Modalitas