obsidianyoutubeautomation

Automated YouTube Notes Pipeline for Obsidian

Search YouTube via API, extract metadata, and create structured Obsidian notes with frontmatter automatically.

5 min read

Watching a YouTube video and manually creating an Obsidian note with the title, channel, description, and your timestamps is tedious. Automate it. Search YouTube via API, extract video metadata, and generate Obsidian-ready Markdown notes with frontmatter. This pipeline runs in under a second per video.

What this pipeline does

  • Searches YouTube for videos matching your topic or URL
  • Extracts structured metadata: title, channel, publish date, description, thumbnail
  • Generates an Obsidian Markdown note with YAML frontmatter
  • Creates bidirectional links to related topic notes in your vault
  • Saves directly to your vault folder

Be honest: metadata only, not transcripts

This pipeline extracts video metadata from YouTube search results. It does not transcribe the video. For transcripts, you need the YouTube Data API with captions access or a third-party transcription service like AssemblyAI or Whisper. The search API gives you everything visible on the search results page: title, channel, description snippet, publish date, view count, and duration. That is enough for a useful reference note, but not a full content summary.

The core pipeline

Python
import requests, os, re
from datetime import date

H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
URL = 'https://api.scavio.dev/api/v1/search'

def youtube_to_obsidian(query: str, vault_path: str, num_results: int = 5):
    """Search YouTube and create Obsidian notes for each result."""
    resp = requests.post(URL, headers=H,
        json={'platform': 'youtube', 'query': query, 'num': num_results},
        timeout=15)
    videos = resp.json().get('organic_results', [])

    created = []
    for video in videos:
        title = video.get('title', 'Untitled')
        slug = re.sub(r'[^a-z0-9]+', '-', title.lower()).strip('-')

        frontmatter = f"""---
title: "{title}"
channel: "{video.get('channel', {}).get('name', 'Unknown')}"
published: "{video.get('date', 'Unknown')}"
url: "{video.get('link', '')}"
duration: "{video.get('duration', 'Unknown')}"
type: youtube-note
created: {date.today().isoformat()}
tags: [youtube, {query.replace(' ', '-')}]
---"""

        body = f"""# {title}

## Source
- Channel: {video.get('channel', {}).get('name', 'Unknown')}
- URL: {video.get('link', '')}
- Duration: {video.get('duration', 'Unknown')}

## Description
{video.get('snippet', 'No description available.')}

## My Notes
-

## Related
- [[{query}]]
"""
        filepath = f"{vault_path}/youtube/{slug}.md"
        os.makedirs(f"{vault_path}/youtube", exist_ok=True)
        with open(filepath, 'w') as f:
            f.write(f"{frontmatter}\n\n{body}")
        created.append(filepath)

    return created

notes = youtube_to_obsidian('fastapi deployment 2026', '/path/to/vault')
print(f"Created {len(notes)} notes")

Templater integration

If you use the Obsidian Templater plugin, you can trigger this pipeline from within Obsidian. Create a template that calls a local Python script and inserts the result.

JavaScript
// Obsidian Templater user script: youtube_search.js
// Place in your Templater scripts folder

async function youtube_search(tp) {
    const query = await tp.system.prompt("YouTube search query:");
    if (!query) return "No query provided.";

    // Call local API proxy (Python Flask running on localhost)
    const resp = await fetch('http://localhost:5111/youtube-search', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({query: query, num: 3})
    });
    const data = await resp.json();

    let output = "";
    for (const video of data.videos) {
        output += "## " + video.title + "\n";
        output += "- Channel: " + video.channel + "\n";
        output += "- URL: " + video.url + "\n";
        output += "- Duration: " + video.duration + "\n\n";
    }
    return output;
}

module.exports = youtube_search;

The local API proxy

Templater cannot call external APIs directly with API keys. Run a small Flask server locally that proxies the search request.

Python
from flask import Flask, request, jsonify
import requests, os

app = Flask(__name__)
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
URL = 'https://api.scavio.dev/api/v1/search'

@app.route('/youtube-search', methods=['POST'])
def youtube_search():
    data = request.json
    query = data.get('query', '')
    num = data.get('num', 5)

    resp = requests.post(URL, headers=H,
        json={'platform': 'youtube', 'query': query, 'num': num},
        timeout=15)
    results = resp.json().get('organic_results', [])

    videos = [{
        'title': r.get('title', ''),
        'channel': r.get('channel', {}).get('name', ''),
        'url': r.get('link', ''),
        'duration': r.get('duration', ''),
        'snippet': r.get('snippet', '')
    } for r in results]

    return jsonify({'videos': videos})

if __name__ == '__main__':
    app.run(port=5111)

Batch processing a playlist topic

Research a topic thoroughly by searching multiple related queries and creating a note for each unique video found.

Python
import requests, os

H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
URL = 'https://api.scavio.dev/api/v1/search'

def batch_research(topic: str, sub_queries: list[str]) -> list[dict]:
    """Search multiple related queries, deduplicate results."""
    seen_urls = set()
    unique_videos = []

    for q in sub_queries:
        resp = requests.post(URL, headers=H,
            json={'platform': 'youtube', 'query': f'{topic} {q}'}, timeout=15)
        for r in resp.json().get('organic_results', []):
            url = r.get('link', '')
            if url not in seen_urls:
                seen_urls.add(url)
                unique_videos.append(r)
    return unique_videos

videos = batch_research('kubernetes', ['tutorial beginner', 'production setup', 'debugging'])
print(f"Found {len(videos)} unique videos across 3 sub-queries")

Cost

A typical research session might search 10-20 queries. That is 10-20 API credits. At 500 free credits per month, you can run 25-50 research sessions before hitting the limit. For heavy researchers, $30/mo for 7,000 credits covers daily research without thinking about usage. Each credit costs $0.005.