Skip to main content
MoneyPrinter searches for stock videos on Pexels based on AI-generated search terms. The system automatically finds high-quality, relevant footage for your video content.

Core Function

The main search function is search_for_stock_videos() in Backend/search.py:
def search_for_stock_videos(query: str, api_key: str, it: int, min_dur: int) -> List[str]:
    """
    Searches for stock videos based on a query.
    
    Args:
        query (str): The query to search for.
        api_key (str): The Pexels API key to use.
        it (int): Number of videos to fetch per query.
        min_dur (int): Minimum duration in seconds for each video.
    
    Returns:
        List[str]: A list of stock video URLs.
    """
Location: Backend/search.py:6-66

How It Works

1

Generate Search Terms

The AI generates contextual search terms from the script using get_search_terms() from Backend/gpt.py.
2

Query Pexels API

Each search term is sent to the Pexels Video Search API to fetch matching videos.
3

Filter by Duration

Videos shorter than min_dur are excluded to ensure sufficient footage.
4

Select Best Quality

The highest resolution version of each video is selected based on width × height.

Pexels API Integration

Authentication

The Pexels API requires an API key passed in the Authorization header:
headers = {
    "Authorization": api_key
}

API Endpoint

qurl = f"https://api.pexels.com/videos/search?query={query}&per_page={it}"
r = requests.get(qurl, headers=headers)
response = r.json()
Get a free Pexels API key at pexels.com/api. The free tier allows 200 requests per hour.

Search Term Generation

Search terms are generated by the AI to match the video content:
def get_search_terms(
    video_subject: str, amount: int, script: str, ai_model: str
) -> List[str]:
    """
    Generate a JSON-Array of search terms for stock videos,
    depending on the subject of a video.
    """
Location: Backend/gpt.py:237-312

Prompt Template

The AI receives this prompt:
prompt = f"""
Generate {amount} search terms for stock videos,
depending on the subject of a video.
Subject: {video_subject}

The search terms are to be returned as
a JSON-Array of strings.

Each search term should consist of 1-3 words,
always add the main subject of the video.

YOU MUST ONLY RETURN THE JSON-ARRAY OF STRINGS.
YOU MUST NOT RETURN ANYTHING ELSE.

For context, here is the full text:
{script}
"""

Example Output

[
  "space exploration rocket",
  "astronaut spacewalk",
  "mars rover",
  "space station orbit",
  "galaxy nebula"
]

Video Quality Selection

MoneyPrinter selects the highest resolution video available:
for video in raw_urls:
    # Check if video has a valid download link
    if ".com/video-files" in video["link"]:
        # Only save the URL with the largest resolution
        if (video["width"] * video["height"]) > video_res:
            temp_video_url = video["link"]
            video_res = video["width"] * video["height"]

Resolution Priority

  1. Calculates resolution as width × height
  2. Tracks the highest resolution found
  3. Returns the URL with maximum pixel count
  4. Validates the URL contains .com/video-files
Pexels returns multiple versions of each video in different resolutions. MoneyPrinter automatically picks the best quality for crisp, professional-looking output.

Duration Filtering

Videos are filtered by minimum duration to ensure enough footage:
for i in range(it):
    # Check if video has desired minimum duration
    if response["videos"][i]["duration"] < min_dur:
        continue
    # Process video...
If all videos are shorter than min_dur, the function may return fewer videos than requested. The video combination logic will loop through available clips to reach the target duration.

Usage Example

from Backend.search import search_for_stock_videos
from Backend.gpt import get_search_terms

# Generate search terms from script
script = "Space exploration has revolutionized our understanding..."
search_terms = get_search_terms(
    video_subject="Space Exploration",
    amount=5,
    script=script,
    ai_model="llama3.1:8b"
)

print(f"Search terms: {search_terms}")
# Output: ['space exploration', 'astronaut mission', 'rocket launch', ...]

# Search for videos for each term
api_key = "YOUR_PEXELS_API_KEY"
video_urls = []

for term in search_terms:
    urls = search_for_stock_videos(
        query=term,
        api_key=api_key,
        it=3,  # Fetch 3 videos per term
        min_dur=5  # Minimum 5 seconds
    )
    video_urls.extend(urls)

print(f"Found {len(video_urls)} videos")

Error Handling

The function includes error handling for API failures:
try:
    # Loop through each video in the result
    for i in range(it):
        # Process videos...
except Exception as e:
    log("[-] No Videos found.", "error")
    log(str(e), "error")

Common Errors

  • 401 Unauthorized: Invalid or missing API key
  • 429 Too Many Requests: Rate limit exceeded (>200/hour on free tier)
  • No Videos Found: Query returned no results
  • Index Error: Fewer than it videos available for the query
The function returns an empty list if no videos are found. The calling code should check for empty results and handle appropriately.

API Response Structure

Pexels returns video data in this format:
{
  "videos": [
    {
      "id": 123456,
      "duration": 15,
      "video_files": [
        {
          "id": 789,
          "link": "https://player.vimeo.com/video-files/...",
          "width": 1920,
          "height": 1080,
          "quality": "hd"
        }
      ]
    }
  ]
}

Logging

The function logs search results:
log(f"\t=> \"{query}\" found {len(video_url)} Videos", "info")
Example output:
=> "space exploration" found 3 Videos
=> "astronaut mission" found 2 Videos
=> "rocket launch" found 3 Videos

Performance Considerations

  • API Rate Limits: Free tier = 200 requests/hour
  • Parallel Requests: Not implemented (sequential processing)
  • Caching: No caching of search results (each run queries fresh)
  • Bandwidth: High-resolution videos are large (10-50MB each)
To reduce API usage, cache search results locally or use a lower it value (e.g., 2-3 videos per term instead of 5-10).

Integration with Pipeline

The search results are passed to the video combination stage:
  1. Search: search_for_stock_videos() returns list of URLs
  2. Download: URLs are downloaded via save_video() in Backend/video.py
  3. Combine: Videos are concatenated in combine_videos()
  4. Final Output: Combined video gets subtitles and audio
See Video Composition for the next pipeline stage.

Build docs developers (and LLMs) love