-
Notifications
You must be signed in to change notification settings - Fork 49
Add script to generate video poster images with auto-detection #13939
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
09c3156
b54ecb6
ffa7509
b27f72b
11ec117
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -37,6 +37,10 @@ const videoFormats: Record<string, string> = { | |||||||||||||||||
| } | ||||||||||||||||||
| const contentType = videoFormats[fileExtension] || 'video/mp4' | ||||||||||||||||||
|
|
||||||||||||||||||
| // Auto-detect poster image: replace video extension with .png | ||||||||||||||||||
| // If no explicit thumbnail is provided, assume poster exists with same name | ||||||||||||||||||
| const posterPath = thumbnail || src.replace(/\.[^.]+$/, '.png') | ||||||||||||||||||
|
Comment on lines
+40
to
+42
|
||||||||||||||||||
| // Auto-detect poster image: replace video extension with .png | |
| // If no explicit thumbnail is provided, assume poster exists with same name | |
| const posterPath = thumbnail || src.replace(/\.[^.]+$/, '.png') | |
| // Auto-detect poster image by swapping the video extension for .png | |
| // If no explicit thumbnail is provided, assume poster exists with same name | |
| const posterPath = thumbnail || (fileExtension | |
| ? `${src.slice(0, -fileExtension.length - 1)}.png` | |
| : `${src}.png`) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,61 @@ | ||||||||||||||||||||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||||||||||||||||||||
| set -e | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Script to generate web-optimized poster images from videos in docs/public/videos | ||||||||||||||||||||||||||||||||||||
| # Posters are extracted at 1 second into the video and saved as PNG files | ||||||||||||||||||||||||||||||||||||
| # alongside the video files (same directory, with .png extension) | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||||||||||||||||||||||||||||||||||||
| REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" | ||||||||||||||||||||||||||||||||||||
| VIDEOS_DIR="$REPO_ROOT/docs/public/videos" | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Check if ffmpeg is installed | ||||||||||||||||||||||||||||||||||||
| if ! command -v ffmpeg &> /dev/null; then | ||||||||||||||||||||||||||||||||||||
| echo "Error: ffmpeg is not installed. Please install it first:" | ||||||||||||||||||||||||||||||||||||
| echo " Ubuntu/Debian: sudo apt-get install ffmpeg" | ||||||||||||||||||||||||||||||||||||
| echo " macOS: brew install ffmpeg" | ||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| echo "Generating poster images from videos in $VIDEOS_DIR" | ||||||||||||||||||||||||||||||||||||
| echo "Posters will be saved alongside video files with .png extension" | ||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Process each MP4 video file | ||||||||||||||||||||||||||||||||||||
| for video in "$VIDEOS_DIR"/*.mp4; do | ||||||||||||||||||||||||||||||||||||
| if [ ! -f "$video" ]; then | ||||||||||||||||||||||||||||||||||||
| echo "No video files found in $VIDEOS_DIR" | ||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
Comment on lines
+24
to
+30
|
||||||||||||||||||||||||||||||||||||
| # Process each MP4 video file | |
| for video in "$VIDEOS_DIR"/*.mp4; do | |
| if [ ! -f "$video" ]; then | |
| echo "No video files found in $VIDEOS_DIR" | |
| exit 1 | |
| fi | |
| # Collect MP4 video files and ensure there is at least one to process | |
| shopt -s nullglob | |
| mp4_files=("$VIDEOS_DIR"/*.mp4) | |
| if [ ${#mp4_files[@]} -eq 0 ]; then | |
| echo "No video files found in $VIDEOS_DIR" | |
| exit 1 | |
| fi | |
| # Process each MP4 video file | |
| for video in "${mp4_files[@]}"; do |
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable name "basename" shadows the bash built-in command of the same name. While this works, it's generally a best practice to avoid using reserved words or built-in command names as variable names to prevent confusion and potential issues.
Consider renaming to something like "video_basename" or "video_name" for clarity.
| basename=$(basename "$video" .mp4) | |
| # Generate the output poster filename (PNG in same directory as video) | |
| poster="$VIDEOS_DIR/${basename}.png" | |
| echo "Processing: $basename.mp4" | |
| video_basename=$(basename "$video" .mp4) | |
| # Generate the output poster filename (PNG in same directory as video) | |
| poster="$VIDEOS_DIR/${video_basename}.png" | |
| echo "Processing: $video_basename.mp4" |
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ffmpeg command uses a fixed scale filter that forces output to 1920x1080 with "force_original_aspect_ratio=decrease". This could result in letterboxing or pillarboxing if the source video has a different aspect ratio.
For videos that aren't 16:9 aspect ratio, this will add black bars to fit within 1920x1080. Consider whether this is the desired behavior, or if you want to preserve the original aspect ratio without forced scaling. Alternatively, you could extract the frame at its native resolution to avoid any quality loss or aspect ratio issues.
| # Extract frame at 1 second, scale to maintain quality | |
| # -ss 1: Seek to 1 second | |
| # -i: Input file | |
| # -vframes 1: Extract only 1 frame | |
| # -q:v 2: High quality (1-31 scale, 2 is very high quality) | |
| # -vf scale: Ensure output is proper size | |
| ffmpeg -ss 1 -i "$video" -vframes 1 -q:v 2 -vf "scale=1920:1080:force_original_aspect_ratio=decrease" "$poster" -y 2>&1 | grep -v "frame=" || true | |
| # Extract frame at 1 second | |
| # -ss 1: Seek to 1 second | |
| # -i: Input file | |
| # -vframes 1: Extract only 1 frame | |
| # -q:v 2: High quality (1-31 scale, 2 is very high quality) | |
| ffmpeg -ss 1 -i "$video" -vframes 1 -q:v 2 "$poster" -y 2>&1 | grep -v "frame=" || true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation states "No need to specify the
thumbnailprop - it's automatically derived from the video path!" However, existing Video component usages in the codebase (e.g., in docs/src/content/docs/setup/creating-workflows.mdx and docs/src/content/docs/setup/quick-start.mdx) still have explicit thumbnail props pointing to non-existent paths like "/gh-aw/images/create-workfow-github-thumbnail.png" and "/gh-aw/images/install-and-add-workflow-in-cli-thumbnail.png".This creates a discrepancy between the documented behavior and actual usage. These files should be updated to either:
Note: The PR description claims "Removed explicit
thumbnailprops from all Video component usages" but this hasn't been done.