Skip to main content
Glama
video_retention_visualization.py14.5 kB
#!/usr/bin/env python3 """ Video Timeline Retention Visualization Example This example demonstrates how to use get_video_timeline_analytics to create retention curves and identify viewer behavior patterns. """ import json import asyncio from datetime import datetime, timedelta # Example of creating retention visualizations from timeline data async def analyze_video_retention(manager, entry_id): """Get and analyze retention data for a video.""" print(f"Analyzing retention for video: {entry_id}") # Get retention data result = await get_video_timeline_analytics( manager, entry_id=entry_id ) data = json.loads(result) if "error" in data: print(f"Error: {data['error']}") return None return data def create_retention_chart_config(retention_data): """Create Chart.js configuration for retention curve.""" retention_curve = retention_data["retention_curve"] insights = retention_data["insights"] # Main retention line retention_dataset = { "label": "Viewer Retention", "data": [{"x": p["percentile"], "y": p["retention_rate"]} for p in retention_curve], "borderColor": "rgb(75, 192, 192)", "backgroundColor": "rgba(75, 192, 192, 0.2)", "tension": 0.4, "fill": True } # Drop-off indicators dropoff_points = [] for drop in insights.get("major_drop_offs", []): dropoff_points.append({ "x": drop["percentile"], "y": next(p["retention_rate"] for p in retention_curve if p["percentile"] == drop["percentile"]) }) dropoff_dataset = { "label": "Major Drop-offs", "data": dropoff_points, "borderColor": "rgb(255, 99, 132)", "backgroundColor": "rgb(255, 99, 132)", "pointRadius": 8, "pointHoverRadius": 10, "showLine": False } # Replay hotspots replay_points = [] for replay in insights.get("replay_hotspots", []): replay_points.append({ "x": replay["percentile"], "y": next(p["retention_rate"] for p in retention_curve if p["percentile"] == replay["percentile"]) }) replay_dataset = { "label": "Replay Hotspots", "data": replay_points, "borderColor": "rgb(255, 205, 86)", "backgroundColor": "rgb(255, 205, 86)", "pointRadius": 8, "pointStyle": "star", "showLine": False } return { "type": "line", "data": { "datasets": [retention_dataset, dropoff_dataset, replay_dataset] }, "options": { "responsive": True, "plugins": { "title": { "display": True, "text": f"Video Retention Analysis - {retention_data['video_id']}" }, "annotation": { "annotations": { "fifty_percent": { "type": "line", "xMin": insights["fifty_percent_point"], "xMax": insights["fifty_percent_point"], "borderColor": "rgb(255, 99, 132)", "borderWidth": 2, "borderDash": [5, 5], "label": { "content": "50% Retention", "enabled": True } } } } }, "scales": { "x": { "type": "linear", "display": True, "title": { "display": True, "text": "Video Progress (%)" }, "min": 0, "max": 100 }, "y": { "display": True, "title": { "display": True, "text": "Retention Rate (%)" }, "min": 0, "max": 100 } } } } def create_heatmap_data(retention_curve): """Create heatmap data showing engagement intensity.""" heatmap_data = [] for i, point in enumerate(retention_curve): # Calculate engagement score based on retention and replays engagement = point["retention_rate"] if point["replays"] > 0 and point["unique_users"] > 0: replay_boost = (point["replays"] / point["unique_users"]) * 20 engagement = min(100, engagement + replay_boost) heatmap_data.append({ "percentile": point["percentile"], "engagement": engagement, "viewers": point["viewers"], "replays": point["replays"] }) return heatmap_data async def compare_cohorts(manager, entry_id): """Compare retention between different viewer cohorts.""" print(f"\nComparing cohorts for video: {entry_id}") # Get data with cohort comparison result = await get_video_timeline_analytics( manager, entry_id=entry_id, user_ids="Unknown", # Anonymous viewers compare_cohorts=True ) data = json.loads(result) if "error" in data: print(f"Error: {data['error']}") return None if "cohort_comparison" in data: all_viewers = data["cohort_comparison"]["all_viewers"] anonymous = data["cohort_comparison"]["filtered_cohort"] print("\nCohort Comparison Insights:") print(f"All Viewers - Avg Retention: {all_viewers['insights']['avg_retention']}%") print(f"Anonymous - Avg Retention: {anonymous['insights']['avg_retention']}%") print(f"All Viewers - Completion: {all_viewers['insights']['completion_rate']}%") print(f"Anonymous - Completion: {anonymous['insights']['completion_rate']}%") return data def generate_retention_report(retention_data): """Generate a text report from retention data.""" insights = retention_data["insights"] report = f""" Video Retention Report ===================== Video ID: {retention_data['video_id']} Date Range: {retention_data['date_range']['from']} to {retention_data['date_range']['to']} Key Metrics: - Average Retention: {insights['avg_retention']}% - 50% Retention Point: {insights['fifty_percent_point']}% of video - Completion Rate: {insights['completion_rate']}% - Engagement Score: {insights['engagement_score']} Major Drop-off Points: """ for drop in insights.get("major_drop_offs", []): report += f"- {drop['percentile']}% mark: {drop['drop_percentage']}% viewer loss\n" report += "\nReplay Hotspots:\n" for replay in insights.get("replay_hotspots", []): report += f"- {replay['percentile']}% mark: {replay['replay_ratio']*100:.1f}% replay rate\n" report += f""" Recommendations: 1. Review content at {insights['fifty_percent_point']}% - this is where you lose half your audience 2. Investigate drop-offs to identify problematic content 3. Extract and promote high-replay segments 4. Consider trimming content after {insights.get('major_drop_offs', [{'percentile': 100}])[0]['percentile']}% if completion is low """ return report def create_engagement_timeline(retention_curve): """Create a timeline showing engagement throughout the video.""" timeline = [] for i in range(0, 101, 10): # Every 10% point = next((p for p in retention_curve if p["percentile"] == i), None) if point: status = "🟢 High" if point["retention_rate"] > 70 else "🟡 Medium" if point["retention_rate"] > 40 else "🔴 Low" replay_indicator = "🔄" if point["replays"] > point["unique_users"] * 0.2 else "" timeline.append({ "position": f"{i}%", "retention": f"{point['retention_rate']:.1f}%", "status": status, "replay": replay_indicator }) return timeline async def main(): """Example usage of video timeline analytics.""" print("Video Timeline Analytics Example") print("================================\n") # Example retention data structure example_data = { "video_id": "1_abc123", "date_range": {"from": "2024-01-01", "to": "2024-01-31"}, "retention_curve": [ {"percentile": 0, "retention_rate": 100.0, "viewers": 1000, "unique_users": 850, "replays": 150}, {"percentile": 10, "retention_rate": 85.0, "viewers": 850, "unique_users": 750, "replays": 100}, {"percentile": 25, "retention_rate": 70.0, "viewers": 700, "unique_users": 650, "replays": 50}, {"percentile": 50, "retention_rate": 55.0, "viewers": 550, "unique_users": 500, "replays": 50}, {"percentile": 75, "retention_rate": 45.0, "viewers": 450, "unique_users": 400, "replays": 50}, {"percentile": 90, "retention_rate": 40.0, "viewers": 400, "unique_users": 350, "replays": 50}, {"percentile": 100, "retention_rate": 38.0, "viewers": 380, "unique_users": 330, "replays": 50} ], "insights": { "avg_retention": 65.5, "fifty_percent_point": 35, "completion_rate": 38.0, "major_drop_offs": [ {"percentile": 10, "drop_percentage": 15.0}, {"percentile": 25, "drop_percentage": 15.0} ], "replay_hotspots": [ {"percentile": 45, "replay_ratio": 0.35}, {"percentile": 78, "replay_ratio": 0.28} ], "engagement_score": 51.75 } } # Generate visualizations print("1. Chart.js Configuration:") chart_config = create_retention_chart_config(example_data) print(json.dumps(chart_config, indent=2)) print("\n2. Engagement Timeline:") timeline = create_engagement_timeline(example_data["retention_curve"]) for point in timeline: print(f"{point['position']}: {point['retention']} {point['status']} {point['replay']}") print("\n3. Retention Report:") report = generate_retention_report(example_data) print(report) print("\n4. Heatmap Data (first 5 points):") heatmap = create_heatmap_data(example_data["retention_curve"]) for point in heatmap[:5]: print(f"Position {point['percentile']}%: Engagement {point['engagement']:.1f}") # HTML Dashboard Example html_dashboard = f""" <!DOCTYPE html> <html> <head> <title>Video Retention Dashboard</title> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation"></script> <style> body {{ font-family: Arial, sans-serif; margin: 20px; background-color: #f5f5f5; }} .container {{ max-width: 1200px; margin: 0 auto; }} .metrics {{ display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-bottom: 30px; }} .metric-card {{ background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); text-align: center; }} .metric-value {{ font-size: 36px; font-weight: bold; color: #333; }} .metric-label {{ font-size: 14px; color: #666; margin-top: 5px; }} .chart-container {{ background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); margin-bottom: 20px; }} </style> </head> <body> <div class="container"> <h1>Video Retention Analysis</h1> <div class="metrics"> <div class="metric-card"> <div class="metric-value">{example_data['insights']['avg_retention']:.1f}%</div> <div class="metric-label">Average Retention</div> </div> <div class="metric-card"> <div class="metric-value">{example_data['insights']['completion_rate']:.1f}%</div> <div class="metric-label">Completion Rate</div> </div> <div class="metric-card"> <div class="metric-value">{example_data['insights']['fifty_percent_point']}%</div> <div class="metric-label">50% Drop-off Point</div> </div> <div class="metric-card"> <div class="metric-value">{example_data['insights']['engagement_score']:.1f}</div> <div class="metric-label">Engagement Score</div> </div> </div> <div class="chart-container"> <canvas id="retentionChart"></canvas> </div> <div class="insights"> <h2>Key Insights</h2> <ul> <li>Major viewer drop-off at {example_data['insights']['major_drop_offs'][0]['percentile']}% mark</li> <li>High replay activity at {example_data['insights']['replay_hotspots'][0]['percentile']}% mark</li> <li>Video retains {example_data['insights']['completion_rate']:.1f}% of initial viewers</li> </ul> </div> </div> <script> const ctx = document.getElementById('retentionChart'); const config = {json.dumps(chart_config)}; new Chart(ctx, config); </script> </body> </html> """ # Save dashboard with open("retention_dashboard.html", "w") as f: f.write(html_dashboard) print("\nGenerated retention_dashboard.html - open in browser to view interactive chart") if __name__ == "__main__": asyncio.run(main())

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/zoharbabin/kaltura-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server