diff --git a/.gitignore b/.gitignore index 143fb90..695640a 100644 --- a/.gitignore +++ b/.gitignore @@ -122,7 +122,7 @@ celerybeat.pid *.sage.py # Environments -.env +/.env .venv env/ venv/ diff --git a/analyzer_templates/video_chapters_dynamic.json b/analyzer_templates/video_chapters_dynamic.json new file mode 100644 index 0000000..8097a98 --- /dev/null +++ b/analyzer_templates/video_chapters_dynamic.json @@ -0,0 +1,54 @@ +{ + "description": "Dynamic Chaptering", + "scenario": "videoShot", + "config": { + "returnDetails": true, + "enableSegmentation": true, + "segmentationMode": "custom", + "segmentationDefinition": "Segment the video into stories or chapters. A story (chapter) in a video is a self-contained portion of the program dedicated to a specific news story, topic, or theme. Each segment typically includes a distinct introduction, development, and (sometimes) a conclusion, and can feature a combination of elements such as reporter narration, interviews, sound bites, relevant footage (B-roll), and graphics.", + "locales": [ + "en-US" + ] + }, + "BaseAnalyzerId": "prebuilt-videoAnalyzer", + "fieldSchema": { + "name": "Content Understanding - Dynamic Chaptering", + "fields": { + "Segments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "SegmentId": { "type": "string" }, + "SegmentType": { + "type": "string", + "method": "generate", + "description": "The short title or a short summary of the story or chapter." + }, + "Scenes": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Description": { + "type": "string", + "method": "generate", + "description": "A five-word description of the scene. A scene is a smaller segment of the segment where a continous block for storytelling unfolds within a specific time, place, and set of characters. A scene can only belong to a single chapter, and cannot overlap with other scenes. Scenes are sequential across the video." + }, + "StartTimestamp": { + "type": "string", + "description": "the start timestamp of the scene" + }, + "EndTimestamp": { + "type": "string", + "description": "the end timestamp of the scene" + } + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/analyzer_templates/video_chapters_structured.json b/analyzer_templates/video_chapters_structured.json new file mode 100644 index 0000000..fc8dc87 --- /dev/null +++ b/analyzer_templates/video_chapters_structured.json @@ -0,0 +1,54 @@ +{ + "description": "Structured Chaptering", + "scenario": "videoShot", + "config": { + "returnDetails": true, + "enableSegmentation": true, + "segmentationMode": "custom", + "segmentationDefinition": "Segment the video into only three chapter types: 'Topic Introduction', 'Details About the Work Done', and 'Outcome, Conclusion and Results'. Reason about the content and determine the best time to segment the video according to these chapter types. Use the timestamp of each image to identify the start and end time of each chapter, and avoid chapter overlap. You must always define the three chapter types, and each chapter must have at least one scene.", + "locales": [ + "en-US" + ] + }, + "BaseAnalyzerId": "prebuilt-videoAnalyzer", + "fieldSchema": { + "name": "Content Understanding - Structured Chaptering", + "fields": { + "Segments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "SegmentId": { "type": "string" }, + "SegmentType": { + "type": "string", + "method": "generate", + "description": "The chapter type for the segment" + }, + "Scenes": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Description": { + "type": "string", + "method": "generate", + "description": "A five-word description of the scene. A scene is a smaller segment of the segment where a continous block for storytelling unfolds within a specific time, place, and set of characters. A scene can only belong to a single chapter, and cannot overlap with other scenes. Scenes are sequential across the video." + }, + "StartTimestamp": { + "type": "string", + "description": "the start timestamp of the scene" + }, + "EndTimestamp": { + "type": "string", + "description": "the end timestamp of the scene" + } + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/notebooks/video_chapters_creation.ipynb b/notebooks/video_chapters_creation.ipynb new file mode 100644 index 0000000..f0950f1 --- /dev/null +++ b/notebooks/video_chapters_creation.ipynb @@ -0,0 +1,375 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "11049ef0", + "metadata": {}, + "source": [ + "# Generating Video Chapters" + ] + }, + { + "cell_type": "markdown", + "id": "beccbe11", + "metadata": {}, + "source": [ + "This notebook demonstrates how to automatically generate video chapters using Azure Content Understanding. By analyzing the video content, the LLM model applies its own reasoning to segment the video into meaningful chapters and scenes, providing concise descriptions and timestamps. This approach enables users to quickly create a structured table of contents for any video, powered by advanced AI understanding." + ] + }, + { + "cell_type": "markdown", + "id": "0a44bdf4", + "metadata": {}, + "source": [ + "\n", + "## Pre-requisites\n", + "1. Follow [README](../README.md#configure-azure-ai-service-resource) to create essential resource that will be used in this sample.\n", + "1. Install required packages" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3dfa60be", + "metadata": {}, + "outputs": [], + "source": [ + "%pip install -r ../requirements.txt" + ] + }, + { + "cell_type": "markdown", + "id": "fcefeaab", + "metadata": {}, + "source": [ + "## Load environment variables" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c69047b", + "metadata": {}, + "outputs": [], + "source": [ + "from dotenv import load_dotenv\n", + "import os\n", + "\n", + "load_dotenv(dotenv_path=\".env\", override=True)\n", + "\n", + "AZURE_AI_SERVICE_ENDPOINT = os.getenv(\"AZURE_AI_SERVICE_ENDPOINT\")\n", + "AZURE_AI_SERVICE_API_VERSION = os.getenv(\"AZURE_AI_SERVICE_API_VERSION\", \"2025-05-01-preview\")\n", + "\n", + "AZURE_OPENAI_ENDPOINT = os.getenv(\"AZURE_OPENAI_ENDPOINT\")\n", + "AZURE_OPENAI_API_VERSION = os.getenv(\"AZURE_OPENAI_API_VERSION\", \"2024-08-01-preview\")\n", + "AZURE_OPENAI_CHAT_DEPLOYMENT_NAME = os.getenv(\"AZURE_OPENAI_CHAT_DEPLOYMENT_NAME\")" + ] + }, + { + "cell_type": "markdown", + "id": "7fe969de", + "metadata": {}, + "source": [ + "If you haven't done so, please authenticate by running **'az login'** through the terminal. This credentials are used to validate that you have access to the resources you defined above.\n", + "\n", + "Make sure you have Azure CLI installed on your system. To install --> curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ea18419", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "## Authehticate if you are running this notebook for the first time.\n", + "\n", + "import subprocess\n", + "\n", + "subprocess.run(\"az login\", shell=True)\n" + ] + }, + { + "cell_type": "markdown", + "id": "78e7d414", + "metadata": {}, + "source": [ + "## File to Analyze\n", + "\n", + "Use the following variable to define what file to analyze. For this example, we will be examining a small tutorial. If you would like to try with your own videos, you could use a small video to get results faster." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7c9fb2b0", + "metadata": {}, + "outputs": [], + "source": [ + "VIDEO_LOCATION = \"https://github.com/Azure-Samples/azure-ai-content-understanding-assets/raw/refs/heads/main/videos/learning/learning2.mp4\"" + ] + }, + { + "cell_type": "markdown", + "id": "19db5e47", + "metadata": {}, + "source": [ + "# Automated Chapter Discovery\n", + "\n", + "We will first use Content Understanding and let service interact with an LLM model to apply its own reasoning to segment the video into meaningful chapters, providing concise descriptions and timestamps." + ] + }, + { + "cell_type": "markdown", + "id": "57b9abf6", + "metadata": {}, + "source": [ + "## Create a Custom Analyzer\n", + "The custom analyzer schema for this notebook is [video_chapters_dynamic.json](../analyzer_templates/video_chapters_dynamic.json). This file defines the schema and configuration for a custom video analyzer that uses AI to dynamically generate chapters and scenes based on its understanding of the video content. The service analyzes the video and determines the most meaningful chapter divisions, providing start and end timestamps for each. The configuration section allows flexible segmentation, enabling the model to reason about the content and organize chapters in a way that best fits.\n", + "\n", + "In this example, we will use the utility class `AzureContentUnderstandingClient` to load the analyzer schema from the template file and submit it to Azure Content Understanding service. Then, we will analyze the video and generate the desired chapter and scene structure.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "40e52230", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "from pathlib import Path\n", + "import json\n", + "import uuid\n", + "\n", + "\n", + "# add the parent directory to the path to use shared modules\n", + "parent_dir = Path(Path.cwd()).parent\n", + "sys.path.append(\n", + " str(parent_dir)\n", + ")\n", + "from python.content_understanding_client import AzureContentUnderstandingClient\n", + "\n", + "from azure.identity import DefaultAzureCredential, get_bearer_token_provider\n", + "credential = DefaultAzureCredential()\n", + "token_provider = get_bearer_token_provider(credential, \"https://cognitiveservices.azure.com/.default\")\n", + "\n", + "# The analyzer template is used to define the schema of the output\n", + "ANALYZER_TEMPLATE_PATH = \"../analyzer_templates/video_chapters_dynamic.json\"\n", + "ANALYZER_ID = \"video_scene_chapter\" + \"_\" + str(uuid.uuid4()) # Unique identifier for the analyzer\n", + "\n", + "# Create the Content Understanding (CU) client\n", + "cu_client = AzureContentUnderstandingClient(\n", + " endpoint=AZURE_AI_SERVICE_ENDPOINT,\n", + " api_version=AZURE_AI_SERVICE_API_VERSION,\n", + " token_provider=token_provider,\n", + " x_ms_useragent=\"azure-ai-content-understanding-python/video_chapters_dynamic\", # This header is used for sample usage telemetry, please comment out this line if you want to opt out.\n", + ")\n", + "\n", + "# Use the client to create an analyzer\n", + "response = cu_client.begin_create_analyzer(\n", + " ANALYZER_ID, analyzer_template_path=ANALYZER_TEMPLATE_PATH)\n", + "result = cu_client.poll_result(response)\n", + "\n", + "print(json.dumps(result, indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "9b85cf38", + "metadata": {}, + "source": [ + "### Use the created analyzer to extract video content\n", + "With the analyzer created, request video content extraction using content understanding." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad31ab6a", + "metadata": {}, + "outputs": [], + "source": [ + "# Submit the video for content analysis\n", + "response = cu_client.begin_analyze(ANALYZER_ID, file_location=VIDEO_LOCATION)\n", + "\n", + "# Wait for the analysis to complete and get the content analysis result\n", + "video_cu_result = cu_client.poll_result(\n", + " response, timeout_seconds=3600) # 1 hour timeout for long videos\n", + "\n", + "# Print the content analysis result\n", + "print(f\"Video Content Understanding result: \", video_cu_result)\n", + "\n", + "# Optional - Delete the analyzer if it is no longer needed\n", + "cu_client.delete_analyzer(ANALYZER_ID)" + ] + }, + { + "cell_type": "markdown", + "id": "afde825e", + "metadata": {}, + "source": [ + "Use the following utility to display results for visual review." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55d1342f", + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "from python.chapters_utility import ChaptersFormatter\n", + "\n", + "# For dynamic chaptering, pass dynamic=True\n", + "full_html = ChaptersFormatter.format_chapters_output(VIDEO_LOCATION, video_cu_result, dynamic=True)\n", + "display(HTML(full_html))" + ] + }, + { + "cell_type": "markdown", + "id": "985e9193", + "metadata": {}, + "source": [ + "# Structured Chapter Creation\n", + "\n", + "Alternatively, you can define a specific structure for chaptering that Content Understanding will use to guide the model. When your request includes information detailing clear chapter types and organization, the service can instruct the model to segment the video according to your desired structure, ensuring consistent and predictable chapter creation.\n", + "\n", + "## Create a Custom Analyzer\n", + "The custom analyzer schema for this notebook is [video_chapters_structured.json](../analyzer_templates/video_chapters_structured.json). This file defines the schema and configuration for a custom video analyzer. In this example, it specifies how a video should be segmented into chapters and scenes, including three chapter types: \"Topic Introduction\", \"Details About the Work Done\", and \"Conclusion or Results\". Each segment contains a list of scenes, with each scene described by a short description, start timestamp, and end timestamp. The configuration section controls segmentation behavior and other analysis options, while the fieldSchema section outlines the expected structure of the output, ensuring chapters and scenes are clearly organized and non-overlapping.\n", + "\n", + "We we will also be using the utility class `AzureContentUnderstandingClient` to load the analyzer schema from the template file and submit it to Azure Content Understanding service. Then, we will analyze the video and generate the desired chapter and scene structure." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0afa000b", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "from pathlib import Path\n", + "import json\n", + "import uuid\n", + "\n", + "\n", + "# add the parent directory to the path to use shared modules\n", + "parent_dir = Path(Path.cwd()).parent\n", + "sys.path.append(\n", + " str(parent_dir)\n", + ")\n", + "from python.content_understanding_client import AzureContentUnderstandingClient\n", + "\n", + "from azure.identity import DefaultAzureCredential, get_bearer_token_provider\n", + "credential = DefaultAzureCredential()\n", + "token_provider = get_bearer_token_provider(credential, \"https://cognitiveservices.azure.com/.default\")\n", + "\n", + "# The analyzer template is used to define the schema of the output\n", + "ANALYZER_TEMPLATE_PATH = \"../analyzer_templates/video_chapters_structured.json\"\n", + "ANALYZER_ID = \"video_scene_chapter\" + \"_\" + str(uuid.uuid4()) # Unique identifier for the analyzer\n", + "\n", + "# Create the Content Understanding (CU) client\n", + "cu_client = AzureContentUnderstandingClient(\n", + " endpoint=AZURE_AI_SERVICE_ENDPOINT,\n", + " api_version=AZURE_AI_SERVICE_API_VERSION,\n", + " token_provider=token_provider,\n", + " x_ms_useragent=\"azure-ai-content-understanding-python/video_chapters_structured\", # This header is used for sample usage telemetry, please comment out this line if you want to opt out.\n", + ")\n", + "\n", + "# Use the client to create an analyzer\n", + "response = cu_client.begin_create_analyzer(\n", + " ANALYZER_ID, analyzer_template_path=ANALYZER_TEMPLATE_PATH)\n", + "result = cu_client.poll_result(response)\n", + "\n", + "print(json.dumps(result, indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "5b9cac5c", + "metadata": {}, + "source": [ + "### Use the created analyzer to extract video content\n", + "It might take some time depending on the video length. Try with short videos to get results faster" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f416bf7", + "metadata": {}, + "outputs": [], + "source": [ + "# Submit the video for content analysis\n", + "response = cu_client.begin_analyze(ANALYZER_ID, file_location=VIDEO_LOCATION)\n", + "\n", + "# Wait for the analysis to complete and get the content analysis result\n", + "video_cu_result = cu_client.poll_result(\n", + " response, timeout_seconds=3600) # 1 hour timeout for long videos\n", + "\n", + "# Print the content analysis result\n", + "print(f\"Video Content Understanding result: \", video_cu_result)\n", + "\n", + "# Optional - Delete the analyzer if it is no longer needed\n", + "cu_client.delete_analyzer(ANALYZER_ID)" + ] + }, + { + "cell_type": "markdown", + "id": "0200883b", + "metadata": {}, + "source": [ + "Use the following utility to display results for visual review." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c744700", + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "from python.chapters_utility import ChaptersFormatter\n", + "\n", + "# For structured chaptering, use default (dynamic=False)\n", + "full_html = ChaptersFormatter.format_chapters_output(VIDEO_LOCATION, video_cu_result)\n", + "display(HTML(full_html))" + ] + }, + { + "cell_type": "markdown", + "id": "54f8d5e2", + "metadata": {}, + "source": [ + "# Conclusion\n", + "\n", + "This notebook has demonstrated how Azure Content Understanding, combined with advanced language models, can automatically generate meaningful chapters and scenes from video content. By leveraging AI-driven analysis, you can quickly create structured, searchable tables of contents for any video, making it easier to navigate and understand complex material. This approach streamlines video processing and enables new possibilities for content organization and discovery." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/video_chapters_structured.ipynb b/notebooks/video_chapters_structured.ipynb new file mode 100644 index 0000000..e0a06ae --- /dev/null +++ b/notebooks/video_chapters_structured.ipynb @@ -0,0 +1,248 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "11049ef0", + "metadata": {}, + "source": [ + "# Structured Video Chaptering" + ] + }, + { + "cell_type": "markdown", + "id": "beccbe11", + "metadata": {}, + "source": [ + "This notebook demonstrates how to automatically generate video chapters that follow a defined structure using Azure Content Understanding and GPT. You can define a specific content structure to be followed by the LLM model to segment the video into meaningful chapters and scenes, providing concise descriptions and timestamps." + ] + }, + { + "cell_type": "markdown", + "id": "0a44bdf4", + "metadata": {}, + "source": [ + "\n", + "## Pre-requisites\n", + "1. Follow [README](../README.md#configure-azure-ai-service-resource) to create essential resource that will be used in this sample.\n", + "1. Install required packages" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3dfa60be", + "metadata": {}, + "outputs": [], + "source": [ + "%pip install -r ../requirements.txt" + ] + }, + { + "cell_type": "markdown", + "id": "fcefeaab", + "metadata": {}, + "source": [ + "## Load environment variables" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c69047b", + "metadata": {}, + "outputs": [], + "source": [ + "from dotenv import load_dotenv\n", + "import os\n", + "\n", + "load_dotenv(dotenv_path=\".env\", override=True)\n", + "\n", + "AZURE_AI_SERVICE_ENDPOINT = os.getenv(\"AZURE_AI_SERVICE_ENDPOINT\")\n", + "AZURE_AI_SERVICE_API_VERSION = os.getenv(\"AZURE_AI_SERVICE_API_VERSION\", \"2025-05-01-preview\")\n", + "\n", + "AZURE_OPENAI_ENDPOINT = os.getenv(\"AZURE_OPENAI_ENDPOINT\")\n", + "AZURE_OPENAI_API_VERSION = os.getenv(\"AZURE_OPENAI_API_VERSION\", \"2024-08-01-preview\")\n", + "AZURE_OPENAI_CHAT_DEPLOYMENT_NAME = os.getenv(\"AZURE_OPENAI_CHAT_DEPLOYMENT_NAME\")" + ] + }, + { + "cell_type": "markdown", + "id": "7fe969de", + "metadata": {}, + "source": [ + "If you haven't done so, please authenticate by running **'az login'** through the terminal. This credentials are used to validate that you have access to the resources you defined above.\n", + "\n", + "Make sure you have Azure CLI installed on your system. To install --> curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ea18419", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "## Authehticate if you are running this notebook for the first time.\n", + "\n", + "import subprocess\n", + "\n", + "subprocess.run(\"az login\", shell=True)\n" + ] + }, + { + "cell_type": "markdown", + "id": "78e7d414", + "metadata": {}, + "source": [ + "## File to Analyze\n", + "\n", + "Use the following variable to define what video file to analyze. For this example, we will be examining a small tutorial." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7c9fb2b0", + "metadata": {}, + "outputs": [], + "source": [ + "VIDEO_LOCATION = \"https://github.com/Azure-Samples/azure-ai-content-understanding-assets/raw/refs/heads/main/videos/learning/learning2.mp4\"" + ] + }, + { + "cell_type": "markdown", + "id": "57b9abf6", + "metadata": {}, + "source": [ + "## Create a custom analyzer and submit the video to generate chapters\n", + "The custom analyzer schema for this notebook is [video_chapters_structured.json](../analyzer_templates/video_chapters_structured.json). This file defines the schema and configuration for a custom video analyzer. It specifies how a video should be segmented into chapters and scenes, including three chapter types: \"Topic Introduction\", \"Details About the Work Done\", and \"Conclusion or Results\". Each segment contains a list of scenes, with each scene described by a short description, start timestamp, and end timestamp. The configuration section controls segmentation behavior and other analysis options, while the fieldSchema section outlines the expected structure of the output, ensuring chapters and scenes are clearly organized and non-overlapping.\n", + "\n", + "In this example, we will use the utility class `AzureContentUnderstandingClient` to load the analyzer schema from the template file and submit it to Azure Content Understanding service. Then, we will analyze the video and generate the desired chapter and scene structure.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "40e52230", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "from pathlib import Path\n", + "import json\n", + "import uuid\n", + "\n", + "\n", + "# add the parent directory to the path to use shared modules\n", + "parent_dir = Path(Path.cwd()).parent\n", + "sys.path.append(\n", + " str(parent_dir)\n", + ")\n", + "from python.content_understanding_client import AzureContentUnderstandingClient\n", + "\n", + "from azure.identity import DefaultAzureCredential, get_bearer_token_provider\n", + "credential = DefaultAzureCredential()\n", + "token_provider = get_bearer_token_provider(credential, \"https://cognitiveservices.azure.com/.default\")\n", + "\n", + "# The analyzer template is used to define the schema of the output\n", + "ANALYZER_TEMPLATE_PATH = \"../analyzer_templates/video_chapters_structured.json\"\n", + "ANALYZER_ID = \"video_scene_chapter\" + \"_\" + str(uuid.uuid4()) # Unique identifier for the analyzer\n", + "\n", + "# Create the Content Understanding (CU) client\n", + "cu_client = AzureContentUnderstandingClient(\n", + " endpoint=AZURE_AI_SERVICE_ENDPOINT,\n", + " api_version=AZURE_AI_SERVICE_API_VERSION,\n", + " token_provider=token_provider,\n", + " x_ms_useragent=\"azure-ai-content-understanding-python/video_chapters_structured\", # This header is used for sample usage telemetry, please comment out this line if you want to opt out.\n", + ")\n", + "\n", + "# Use the client to create an analyzer\n", + "response = cu_client.begin_create_analyzer(\n", + " ANALYZER_ID, analyzer_template_path=ANALYZER_TEMPLATE_PATH)\n", + "result = cu_client.poll_result(response)\n", + "\n", + "print(json.dumps(result, indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "9b85cf38", + "metadata": {}, + "source": [ + "### Use the created analyzer to extract video content\n", + "It might take some time depending on the video length. Try with short videos to get results faster." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad31ab6a", + "metadata": {}, + "outputs": [], + "source": [ + "# Submit the video for content analysis\n", + "response = cu_client.begin_analyze(ANALYZER_ID, file_location=VIDEO_LOCATION)\n", + "\n", + "# Wait for the analysis to complete and get the content analysis result\n", + "video_cu_result = cu_client.poll_result(\n", + " response, timeout_seconds=3600) # 1 hour timeout for long videos\n", + "\n", + "# Print the content analysis result\n", + "print(f\"Video Content Understanding result: \", video_cu_result)\n", + "\n", + "# Optional - Delete the analyzer if it is no longer needed\n", + "cu_client.delete_analyzer(ANALYZER_ID)" + ] + }, + { + "cell_type": "markdown", + "id": "0018b59f", + "metadata": {}, + "source": [ + "We will now display the results with the following code:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55d1342f", + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import display, HTML\n", + "from python.chapters_utility import ChaptersFormatter\n", + "\n", + "full_html = ChaptersFormatter.format_chapters_output(VIDEO_LOCATION, video_cu_result)\n", + "display(HTML(full_html))" + ] + }, + { + "cell_type": "markdown", + "id": "1126b263", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/chapters_utility.py b/python/chapters_utility.py new file mode 100644 index 0000000..3ba76f4 --- /dev/null +++ b/python/chapters_utility.py @@ -0,0 +1,114 @@ + +class ChaptersFormatter: + """Formating Utility for Table of Contents""" + + def format_chapters_output(video_URL, video_cu_result, dynamic=False): + """Formats the chapters output for the video.""" + + toc_html = "
" + toc_html += "Table of Contents
" + + full_html = f""" +
+
{toc_html}
+
+ +
+
+ + """ + + return full_html + +