From aab4dd1f57ac6de2c96ad4c1fb16a8ecd499abc6 Mon Sep 17 00:00:00 2001 From: "ds.chienyuanchang@gmail.com" Date: Mon, 22 Sep 2025 22:20:13 +0000 Subject: [PATCH 1/5] first version --- .../video_chapters_dynamic.json | 54 +++ .../video_chapters_structured.json | 54 +++ notebooks/video_chapters_creation.ipynb | 327 ++++++++++++++++++ python/chapters_utility.py | 121 +++++++ 4 files changed, 556 insertions(+) create mode 100644 analyzer_templates/video_chapters_dynamic.json create mode 100644 analyzer_templates/video_chapters_structured.json create mode 100644 notebooks/video_chapters_creation.ipynb create mode 100644 python/chapters_utility.py diff --git a/analyzer_templates/video_chapters_dynamic.json b/analyzer_templates/video_chapters_dynamic.json new file mode 100644 index 00000000..8097a98e --- /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 00000000..fc8dc877 --- /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 00000000..287fe5ec --- /dev/null +++ b/notebooks/video_chapters_creation.ipynb @@ -0,0 +1,327 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "11049ef0", + "metadata": {}, + "source": [ + "# Generating Video Chapters\n", + "\n", + "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": "eece89d8", + "metadata": {}, + "source": [ + "## Create Azure AI Content Understanding Client\n", + "\n", + "> The [AzureContentUnderstandingClient](../python/content_understanding_client.py) is a utility class providing functions to interact with the Content Understanding API. Before the official release of the Content Understanding SDK, it acts as a lightweight SDK. Please fill in the constants **AZURE_AI_ENDPOINT** and **AZURE_AI_API_VERSION** with your Azure AI Service information. Optionally, you may provide **AZURE_AI_API_KEY** if your setup requires key-based authentication.\n", + "\n", + "> ⚠️ Important:\n", + "Please update the code below to match your Azure authentication method.\n", + "Look for the `# IMPORTANT` comments and modify those sections accordingly.\n", + "Skipping this step may cause the sample to not run correctly.\n", + "\n", + "> ⚠️ Note: Using a subscription key works, but using a token provider with Azure Active Directory (AAD) is safer and highly recommended for production environments." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a726d40", + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "import json\n", + "import os\n", + "import sys\n", + "import uuid\n", + "from pathlib import Path\n", + "from dotenv import find_dotenv, load_dotenv\n", + "from azure.identity import DefaultAzureCredential, get_bearer_token_provider\n", + "\n", + "load_dotenv(find_dotenv())\n", + "logging.basicConfig(level=logging.INFO)\n", + "\n", + "# For authentication, you can use either token-based authentication or a subscription key; only one method is required.\n", + "AZURE_AI_ENDPOINT = os.getenv(\"AZURE_AI_ENDPOINT\")\n", + "# IMPORTANT: Replace with your actual subscription key or set it in the \".env\" file if not using token authentication.\n", + "AZURE_AI_API_KEY = os.getenv(\"AZURE_AI_API_KEY\")\n", + "AZURE_AI_API_VERSION = os.getenv(\"AZURE_AI_API_VERSION\", \"2025-05-01-preview\")\n", + "\n", + "# Add the parent directory to the path to use shared modules\n", + "parent_dir = Path(Path.cwd()).parent\n", + "sys.path.append(str(parent_dir))\n", + "from python.content_understanding_client import AzureContentUnderstandingClient\n", + "\n", + "credential = DefaultAzureCredential()\n", + "token_provider = get_bearer_token_provider(credential, \"https://cognitiveservices.azure.com/.default\")\n", + "\n", + "client = AzureContentUnderstandingClient(\n", + " endpoint=AZURE_AI_ENDPOINT,\n", + " api_version=AZURE_AI_API_VERSION,\n", + " # IMPORTANT: Comment out token_provider if using subscription key\n", + " token_provider=token_provider,\n", + " # IMPORTANT: Uncomment this if using subscription key\n", + " # subscription_key=AZURE_AI_API_KEY,\n", + " x_ms_useragent=\"azure-ai-content-understanding-python/video_chapters\", # This header is used for sample usage telemetry; please comment out this line if you wish to opt out.\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_FILE_PATH = Path(\"../data/FlightSimulator.mp4\")" + ] + }, + { + "cell_type": "markdown", + "id": "0edfcab1", + "metadata": {}, + "source": [ + "# 1. 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.\n", + "\n", + "The custom analyzer schema template for this approach 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." + ] + }, + { + "cell_type": "markdown", + "id": "9d502b2e", + "metadata": {}, + "source": [ + "### Load Analyzer Template" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "151faa51", + "metadata": {}, + "outputs": [], + "source": [ + "analyzer_template_path = \"../analyzer_templates/video_chapters_dynamic.json\"\n", + "with open(analyzer_template_path, 'r') as f:\n", + " template_content = json.load(f)\n", + " print(json.dumps(template_content, indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "0c75e230", + "metadata": {}, + "source": [ + "### Create and Run Marketing Video Analyzer" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "40e52230", + "metadata": {}, + "outputs": [], + "source": [ + "video_analyzer_id = \"video_scene_chapter\" + \"_\" + str(uuid.uuid4())\n", + "\n", + "print(f\"Creating chapter video analyzer: {video_analyzer_id}\")\n", + "response = client.begin_create_analyzer(video_analyzer_id, analyzer_template_path=analyzer_template_path)\n", + "result = client.poll_result(response)\n", + "print(\"✅ Chapter video analyzer created successfully!\")\n", + "\n", + "print(f\"Analyzing chapter video: {VIDEO_FILE_PATH}\")\n", + "print(\"⏳ Note: Video analysis may take significantly longer than document analysis...\")\n", + "response = client.begin_analyze(video_analyzer_id, file_location=VIDEO_FILE_PATH)\n", + "result_json = client.poll_result(response, timeout_seconds=360) # Video analysis may take longer, please adjust timeout as needed\n", + "\n", + "print(\"Video Content Understanding result: \")\n", + "print(json.dumps(result, indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "9b85cf38", + "metadata": {}, + "source": [ + "### Extract Video Content from Analyzed Result\n", + "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_FILE_PATH, result_json, dynamic=True)\n", + "display(HTML(full_html))" + ] + }, + { + "cell_type": "markdown", + "id": "985e9193", + "metadata": {}, + "source": [ + "## 2. 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", + "The custom analyzer schema template for this approach 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": "markdown", + "id": "837ef148", + "metadata": {}, + "source": [ + "### Load Analyzer Template" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "558af576", + "metadata": {}, + "outputs": [], + "source": [ + "analyzer_template_path = \"../analyzer_templates/video_chapters_structured.json\"\n", + "with open(analyzer_template_path, 'r') as f:\n", + " template_content = json.load(f)\n", + " print(json.dumps(template_content, indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "ee269be2", + "metadata": {}, + "source": [ + "### Create and Run Marketing Video Analyzer" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1bbd27bd", + "metadata": {}, + "outputs": [], + "source": [ + "video_analyzer_id = \"video_scene_chapter\" + \"_\" + str(uuid.uuid4())\n", + "\n", + "print(f\"Creating chapter video analyzer: {video_analyzer_id}\")\n", + "response = client.begin_create_analyzer(video_analyzer_id, analyzer_template_path=analyzer_template_path)\n", + "result = client.poll_result(response)\n", + "print(\"✅ Chapter video analyzer created successfully!\")\n", + "\n", + "print(f\"Analyzing chapter video: {VIDEO_FILE_PATH}\")\n", + "print(\"⏳ Note: Video analysis may take significantly longer than document analysis...\")\n", + "response = client.begin_analyze(video_analyzer_id, file_location=VIDEO_FILE_PATH)\n", + "result_json = client.poll_result(response, timeout_seconds=360) # Video analysis may take longer, please adjust timeout as needed\n", + "\n", + "print(\"Video Content Understanding result: \")\n", + "print(json.dumps(result, indent=2))" + ] + }, + { + "cell_type": "markdown", + "id": "e8f5f191", + "metadata": {}, + "source": [ + "### Extract Video Content from Analyzed Result\n", + "Use the following utility to display results for visual review." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52b303cd", + "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_FILE_PATH, result_json)\n", + "display(HTML(full_html))" + ] + }, + { + "cell_type": "markdown", + "id": "54f8d5e2", + "metadata": {}, + "source": [ + "# Conclusion\n", + "\n", + "This notebook has demonstrated how **Azure Content Understanding** 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.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/chapters_utility.py b/python/chapters_utility.py new file mode 100644 index 00000000..ae039777 --- /dev/null +++ b/python/chapters_utility.py @@ -0,0 +1,121 @@ + +from typing import Any, Dict + +class ChaptersFormatter: + """Formating Utility for Table of Contents""" + + @staticmethod + def format_chapters_output( + video_URL: str, + video_cu_result: Dict[str, Any], + dynamic: bool = False + ) -> str: + """Formats the chapters output for the video.""" + + toc_html = "
" + toc_html += "Table of Contents
" + + full_html = f""" +
+
{toc_html}
+
+ +
+
+ + """ + + return full_html + + From 9ad381a27145b469d40461366feefbfd4807b9c6 Mon Sep 17 00:00:00 2001 From: "ds.chienyuanchang@gmail.com" Date: Mon, 22 Sep 2025 22:24:01 +0000 Subject: [PATCH 2/5] format json --- analyzer_templates/video_chapters_dynamic.json | 4 +++- analyzer_templates/video_chapters_structured.json | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/analyzer_templates/video_chapters_dynamic.json b/analyzer_templates/video_chapters_dynamic.json index 8097a98e..9c547fbb 100644 --- a/analyzer_templates/video_chapters_dynamic.json +++ b/analyzer_templates/video_chapters_dynamic.json @@ -19,7 +19,9 @@ "items": { "type": "object", "properties": { - "SegmentId": { "type": "string" }, + "SegmentId": { + "type": "string" + }, "SegmentType": { "type": "string", "method": "generate", diff --git a/analyzer_templates/video_chapters_structured.json b/analyzer_templates/video_chapters_structured.json index fc8dc877..744f1a21 100644 --- a/analyzer_templates/video_chapters_structured.json +++ b/analyzer_templates/video_chapters_structured.json @@ -19,7 +19,9 @@ "items": { "type": "object", "properties": { - "SegmentId": { "type": "string" }, + "SegmentId": { + "type": "string" + }, "SegmentType": { "type": "string", "method": "generate", From 58a3b3d73e9bcb6eab236d9240527380d2a183fa Mon Sep 17 00:00:00 2001 From: Chien Yuan Chang Date: Mon, 22 Sep 2025 15:39:09 -0700 Subject: [PATCH 3/5] docs: review notebooks/video_chapters_creation.ipynb (#105) --- notebooks/video_chapters_creation.ipynb | 39 ++++++++++++------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/notebooks/video_chapters_creation.ipynb b/notebooks/video_chapters_creation.ipynb index 287fe5ec..2ac1b401 100644 --- a/notebooks/video_chapters_creation.ipynb +++ b/notebooks/video_chapters_creation.ipynb @@ -15,10 +15,9 @@ "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" + "1. Please follow the [README](../README.md#configure-azure-ai-service-resource) to create the essential resource needed for this sample.\n", + "2. Install the required packages." ] }, { @@ -38,14 +37,14 @@ "source": [ "## Create Azure AI Content Understanding Client\n", "\n", - "> The [AzureContentUnderstandingClient](../python/content_understanding_client.py) is a utility class providing functions to interact with the Content Understanding API. Before the official release of the Content Understanding SDK, it acts as a lightweight SDK. Please fill in the constants **AZURE_AI_ENDPOINT** and **AZURE_AI_API_VERSION** with your Azure AI Service information. Optionally, you may provide **AZURE_AI_API_KEY** if your setup requires key-based authentication.\n", + "> The [AzureContentUnderstandingClient](../python/content_understanding_client.py) is a utility class providing functions to interact with the Content Understanding API. Before the official release of the Content Understanding SDK, this acts as a lightweight SDK. Please fill in the constants **AZURE_AI_ENDPOINT** and **AZURE_AI_API_VERSION** with your Azure AI Service information. Optionally, you may provide **AZURE_AI_API_KEY** if your setup requires key-based authentication.\n", "\n", "> ⚠️ Important:\n", "Please update the code below to match your Azure authentication method.\n", - "Look for the `# IMPORTANT` comments and modify those sections accordingly.\n", + "Look for the `# IMPORTANT` comments and kindly modify those sections accordingly.\n", "Skipping this step may cause the sample to not run correctly.\n", "\n", - "> ⚠️ Note: Using a subscription key works, but using a token provider with Azure Active Directory (AAD) is safer and highly recommended for production environments." + "> ⚠️ Note: While using a subscription key works, using a token provider with Azure Active Directory (AAD) is safer and highly recommended for production environments." ] }, { @@ -69,7 +68,7 @@ "\n", "# For authentication, you can use either token-based authentication or a subscription key; only one method is required.\n", "AZURE_AI_ENDPOINT = os.getenv(\"AZURE_AI_ENDPOINT\")\n", - "# IMPORTANT: Replace with your actual subscription key or set it in the \".env\" file if not using token authentication.\n", + "# IMPORTANT: Please replace with your actual subscription key or set it in the \".env\" file if not using token authentication.\n", "AZURE_AI_API_KEY = os.getenv(\"AZURE_AI_API_KEY\")\n", "AZURE_AI_API_VERSION = os.getenv(\"AZURE_AI_API_VERSION\", \"2025-05-01-preview\")\n", "\n", @@ -99,7 +98,7 @@ "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." + "Use the following variable to define the file to analyze. For this example, we will be examining a small tutorial video. If you would like to try with your own videos, please use a small video to get faster results." ] }, { @@ -119,11 +118,11 @@ "source": [ "# 1. 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.\n", + "We will first use Content Understanding and allow the service to interact with an LLM model, enabling it to apply its own reasoning to segment the video into meaningful chapters. It will provide concise descriptions with timestamps.\n", "\n", - "The custom analyzer schema template for this approach 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", + "The custom analyzer schema template for this approach 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 identifies 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 appropriately.\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." + "In this example, we will use the utility class `AzureContentUnderstandingClient` to load the analyzer schema from the template file and submit it to the Azure Content Understanding service. Then, we will analyze the video and generate the desired chapter and scene structure." ] }, { @@ -152,7 +151,7 @@ "id": "0c75e230", "metadata": {}, "source": [ - "### Create and Run Marketing Video Analyzer" + "### Create and Run Video Chapter Analyzer" ] }, { @@ -184,7 +183,7 @@ "metadata": {}, "source": [ "### Extract Video Content from Analyzed Result\n", - "Use the following utility to display results for visual review." + "Use the following utility to display results for your visual review." ] }, { @@ -213,7 +212,7 @@ "\n", "The custom analyzer schema template for this approach 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." + "We will also be using the utility class `AzureContentUnderstandingClient` to load the analyzer schema from the template file and submit it to the Azure Content Understanding service. Then, we will analyze the video and generate the desired chapter and scene structure." ] }, { @@ -242,7 +241,7 @@ "id": "ee269be2", "metadata": {}, "source": [ - "### Create and Run Marketing Video Analyzer" + "### Create and Run Video Chapter Analyzer" ] }, { @@ -262,7 +261,7 @@ "print(f\"Analyzing chapter video: {VIDEO_FILE_PATH}\")\n", "print(\"⏳ Note: Video analysis may take significantly longer than document analysis...\")\n", "response = client.begin_analyze(video_analyzer_id, file_location=VIDEO_FILE_PATH)\n", - "result_json = client.poll_result(response, timeout_seconds=360) # Video analysis may take longer, please adjust timeout as needed\n", + "result_json = client.poll_result(response, timeout_seconds=360) # Video analysis may take longer, please adjust the timeout as needed\n", "\n", "print(\"Video Content Understanding result: \")\n", "print(json.dumps(result, indent=2))" @@ -274,7 +273,7 @@ "metadata": {}, "source": [ "### Extract Video Content from Analyzed Result\n", - "Use the following utility to display results for visual review." + "Use the following utility to display results for your visual review." ] }, { @@ -287,7 +286,7 @@ "from IPython.display import display, HTML\n", "from python.chapters_utility import ChaptersFormatter\n", "\n", - "# For structured chaptering, use default (dynamic=False)\n", + "# For structured chaptering, use the default (dynamic=False)\n", "full_html = ChaptersFormatter.format_chapters_output(VIDEO_FILE_PATH, result_json)\n", "display(HTML(full_html))" ] @@ -299,7 +298,7 @@ "source": [ "# Conclusion\n", "\n", - "This notebook has demonstrated how **Azure Content Understanding** 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." + "This notebook has demonstrated how **Azure Content Understanding** 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 exciting new possibilities for content organization and discovery." ] } ], @@ -324,4 +323,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file From faef4da6ae8389f2baa5cb8b603d8b4fd6c140af Mon Sep 17 00:00:00 2001 From: "ds.chienyuanchang@gmail.com" Date: Mon, 22 Sep 2025 22:57:31 +0000 Subject: [PATCH 4/5] improve a sentence --- notebooks/video_chapters_creation.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notebooks/video_chapters_creation.ipynb b/notebooks/video_chapters_creation.ipynb index 2ac1b401..a655f60d 100644 --- a/notebooks/video_chapters_creation.ipynb +++ b/notebooks/video_chapters_creation.ipynb @@ -98,7 +98,7 @@ "source": [ "## File to Analyze\n", "\n", - "Use the following variable to define the file to analyze. For this example, we will be examining a small tutorial video. If you would like to try with your own videos, please use a small video to get faster results." + "Use the following variable to specify the file to analyze. For this tutorial, we will examine a short example video. To try your own videos, replace the file path accordingly. For longer videos, you may need to adjust the `timeout` variable in `poll_result`." ] }, { @@ -323,4 +323,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} From 84757b23bcf3c8026fdf509da7924e05ce167243 Mon Sep 17 00:00:00 2001 From: "ds.chienyuanchang@gmail.com" Date: Mon, 22 Sep 2025 23:50:09 +0000 Subject: [PATCH 5/5] add remove analyzer --- notebooks/video_chapters_creation.ipynb | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/notebooks/video_chapters_creation.ipynb b/notebooks/video_chapters_creation.ipynb index a655f60d..3d53451e 100644 --- a/notebooks/video_chapters_creation.ipynb +++ b/notebooks/video_chapters_creation.ipynb @@ -201,6 +201,26 @@ "display(HTML(full_html))" ] }, + { + "cell_type": "markdown", + "id": "1cd3dba6", + "metadata": {}, + "source": [ + "### [Optional] Clean Up Marketing Video Analyzer\n", + "\n", + "Note: In production environments, analyzers are typically kept for reuse rather than deleting." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7b4fb48c", + "metadata": {}, + "outputs": [], + "source": [ + "client.delete_analyzer(video_analyzer_id)" + ] + }, { "cell_type": "markdown", "id": "985e9193", @@ -291,6 +311,26 @@ "display(HTML(full_html))" ] }, + { + "cell_type": "markdown", + "id": "9ea8577b", + "metadata": {}, + "source": [ + "### [Optional] Clean Up Marketing Video Analyzer\n", + "\n", + "Note: In production environments, analyzers are typically kept for reuse rather than deleting." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a6576c9", + "metadata": {}, + "outputs": [], + "source": [ + "client.delete_analyzer(video_analyzer_id)" + ] + }, { "cell_type": "markdown", "id": "54f8d5e2",