การทำความเข้าใจวิดีโอในเอเจนต์
สกัดเฟรม สรุปวิดีโอ และให้เหตุผลตามลำดับเวลาจากคลิป
การทำความเข้าใจวิดีโอในเอเจนต์ เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
การทำความเข้าใจวิดีโอสำหรับเอเจนต์
LLM ส่วนใหญ่ไม่สามารถประมวลผลไฟล์วิดีโอได้โดยตรง แต่เอเจนต์สามารถวิเคราะห์วิดีโอได้โดยแยกเฟรมตัวแทนและส่งเฟรมเหล่านั้นในรูปภาพ จากนั้นเอเจนต์จะให้เหตุผลจากลำดับภาพเพื่อค้นหาเหตุการณ์ การเปลี่ยนแปลง และรูปแบบที่เกิดขึ้นตามเวลา
การติดตั้ง OpenCV เพื่อแยกเฟรม
OpenCV (cv2) เป็นไลบรารีมาตรฐานสำหรับประมวลผลวิดีโอใน Python ไลบรารีนี้ช่วยให้คุณเปิดไฟล์วิดีโอ อ่านข้อมูลเมตา (อัตราเฟรม ความละเอียด และจำนวนเฟรม) และแยกเฟรมแต่ละเฟรมออกมาเป็นอาร์เรย์ 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)การแยกเฟรมทุก N วินาที
สำหรับงานทำความเข้าใจวิดีโอส่วนใหญ่ คุณไม่จำเป็นต้องใช้ทุกเฟรม การสุ่มตัวอย่างหนึ่งเฟรมทุก N วินาทีจะให้สรุปเนื้อหาวิดีโอที่เป็นตัวแทนได้ หากใช้ความถี่ 1 เฟรมต่อวินาที วิดีโอความยาว 60 วินาทีจะได้ 60 เฟรม
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_framesการตรวจจับการเปลี่ยนฉาก
แทนที่จะสุ่มตัวอย่างแบบสม่ำเสมอ ให้แยกเฟรมที่ ขอบเขตฉาก ซึ่งเป็นช่วงเวลาที่เนื้อหาภาพเปลี่ยนแปลงอย่างมีนัยสำคัญ วิธีนี้ให้เฟรมที่มีข้อมูลมากขึ้นต่อการเรียกใช้ API หนึ่งครั้ง ให้ใช้การหาผลต่างระหว่างเฟรม: หากค่าเฉลี่ยของผลต่างสัมบูรณ์ระหว่างเฟรมต่อเนื่องเกินค่าเกณฑ์ แสดงว่าเกิดการเปลี่ยนฉาก
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 savedการส่งลำดับเฟรมไปยัง API ด้านการมองเห็น
ส่งเฟรมที่แยกไว้หลายเฟรมไปยัง API ด้านการมองเห็นในข้อความเดียว ให้ใส่การประทับเวลาของแต่ละเฟรม เพื่อให้โมเดลให้เหตุผลเกี่ยวกับลำดับตามเวลาและระยะเวลาได้ และขอให้โมเดลใช้การให้เหตุผลตามลำดับเวลาอย่างชัดเจนในพรอมต์
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].textพรอมต์สำหรับการให้เหตุผลตามลำดับเวลา
การให้เหตุผลตามลำดับเวลาต้องอาศัยการกำหนดกรอบพรอมต์ที่เฉพาะเจาะจง ให้ขอโมเดลเปรียบเทียบเฟรมอย่างชัดเจน ระบุสิ่งที่เปลี่ยนแปลง ประเมินระยะเวลาของกิจกรรม และค้นหาความสัมพันธ์เชิงเหตุผลระหว่างเฟรม
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)
ไปป์ไลน์สรุปวิดีโอ
ไปป์ไลน์สรุปวิดีโอที่สมบูรณ์ประกอบด้วย: แยกเฟรม → ส่งเฟรมไปยังโมเดลด้านการมองเห็นเป็นชุด → รวบรวมสรุปของแต่ละชุด → สังเคราะห์เป็นสรุปสุดท้าย การแบ่งเป็นชุดช่วยป้องกันไม่ให้เกินขีดจำกัดหน้าต่างบริบท
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].textการติดตามวัตถุข้ามเฟรม
ขอให้โมเดลด้านการมองเห็นติดตามวัตถุที่ระบุข้ามลำดับเฟรม ตัวอย่างเช่น 'ในแต่ละเฟรม ให้อธิบายตำแหน่งของรถสีแดง: บนซ้าย, บนขวา, ตรงกลาง, ล่างซ้าย, ล่างขวา' วิธีนี้สร้างเส้นทางการเคลื่อนที่แบบคร่าว ๆ ได้โดยไม่ต้องใช้อัลกอริทึมติดตามด้วยคอมพิวเตอร์วิทัศน์
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 trajectoryการจัดการข้อจำกัดจำนวนเฟรม
หน้าต่างบริบทของ API ด้านการมองเห็นมีข้อจำกัดเกี่ยวกับจำนวนรูปภาพที่ส่งได้ต่อคำขอหนึ่งครั้ง (โดยทั่วไปคือ 5–20 รูปภาพ) สำหรับวิดีโอขนาดยาว ให้ใช้แนวทางแบบลำดับชั้น: วิเคราะห์แต่ละส่วนแยกกัน จากนั้นรวมสรุปของแต่ละส่วนเป็นสรุปสุดท้ายโดยใช้การเรียกใช้ LLM ครั้งที่สอง
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].textการรวมการวิเคราะห์เสียงและวิดีโอ
เพื่อให้เข้าใจได้อย่างครบถ้วนที่สุด ให้รวมการวิเคราะห์ภาพระดับเฟรมเข้ากับการถอดเสียงด้วย Whisper เอเจนต์สามารถเชื่อมโยงสิ่งที่ เห็น กับสิ่งที่ พูด ในแต่ละการประทับเวลาได้ ทำให้รองรับงานที่มีประโยชน์ เช่น การวิเคราะห์การประชุมหรือการทำดัชนีบทเรียน
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)
}การล้างข้อมูลและจัดการเฟรม
เฟรมที่แยกออกมาอาจสะสมอย่างรวดเร็ว ให้ล้างไฟล์เฟรมชั่วคราวหลังประมวลผลเสร็จเสมอ และสร้างแคชเฟรมโดยใช้แฮชของ (เส้นทางวิดีโอ, อัตราเฟรม) เป็นคีย์ เพื่อหลีกเลี่ยงการแยกเฟรมซ้ำเมื่อวิเคราะห์วิดีโอเดิมอีกครั้ง
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')ตรวจสอบความรู้
เหตุใดการตรวจจับการเปลี่ยนฉากจึงเหมาะกว่าการสุ่มตัวอย่างเฟรมแบบสม่ำเสมอสำหรับการวิเคราะห์วิดีโอ
สรุป: การทำความเข้าใจวิดีโอในเอเจนต์
ทำได้ดีมาก! ประเด็นสำคัญจากบทเรียนนี้มีดังนี้:
- OpenCV: แยกเฟรมด้วย
cap.read()และสุ่มตัวอย่างทุก N วินาทีหรือเมื่อเกิดการเปลี่ยนฉาก - ลำดับเฟรม: ส่งตามลำดับเวลาโดยใส่การประทับเวลาเพื่อให้มีบริบทตามเวลา
- การวิเคราะห์แบบลำดับชั้น: แบ่งเป็นชุด → สรุปแต่ละส่วน → สังเคราะห์เป็นสรุปสุดท้าย
- การวิเคราะห์ร่วม: ffmpeg แยกเสียง Whisper ถอดเสียง และอ้างอิงไขว้กับเฟรมภาพ
- แคชเฟรม: หลีกเลี่ยงการแยกเฟรมซ้ำด้วยไดเรกทอรีแคชที่ใช้แฮชเป็นคีย์
ถัดไป: การให้เหตุผลข้ามรูปแบบ — เมื่อข้อความกล่าวอย่างหนึ่ง แต่ภาพแสดงอีกอย่างหนึ่ง
คำถามที่พบบ่อย
บทเรียน “การทำความเข้าใจวิดีโอในเอเจนต์” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การทำความเข้าใจวิดีโอในเอเจนต์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การทำความเข้าใจวิดีโอในเอเจนต์”
สกัดเฟรม สรุปวิดีโอ และให้เหตุผลตามลำดับเวลาจากคลิป คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การทำความเข้าใจวิดีโอในเอเจนต์” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม
ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เอเจนต์ภาพ + ข้อความด้วย Claude Vision และ GPT-4V
- เวิร์กโฟลว์เอเจนต์เสียง + ข้อความ
- การทำความเข้าใจวิดีโอในเอเจนต์
- รูปแบบการให้เหตุผลข้ามสื่อ