Contents

How I Stream Videos for Incremental Video in Obsidian

Abstract

TL;DR:

I. Incremental Writing Plugin for Obsidian for Incremental Video in Obsidian

II. yt-dlp '{}' -o - | mpv - to stream YouTube videos

Introduction

Almost two years ago I wrote Incremental Video: How I Watch Local Videos in SuperMemo. Since then my study/workflow has changed a lot: I moved away from SuperMemo to Obsidian and fully embraced Linux and the CLI. In this article I’ll show how I use Obsidian in combination with some CLI tools to do Incremental Video.

1. Problem: Contrived SuperMemo setup in Linux

What I used to do: Fire up Virtual Machine(VM) -> Fire Up Windows -> Fire Up SuperMemo. I also used to batch load all my videos from my Linux host to Windows guest with a bridged networking mode. Then import all videos from Windows’s file system to SuperMemo. Needless to say it’s a very complicated setup.

Solution: Use Incremental Writing Plugin for Obsidian for Incremental Video

After I’ve moved away from SuperMemo, I use Incremental Writing Plugin for Obsidian, which is developed by James. Getting Started and Incremental Writing in Obsidian.

I use this plugin for more than Incremental Writing. To me, it’s a review scheduler so that it’ll handle when I’ll watch a particular video. Before, I just had a folder called “pending-videos” with all the downloaded videos, but I never got around to watching. If you’re interested in the rationale behind, please check out my Incremental Reading: Reading the Same Article Two Years Later.

My video queue

./images/queue.png

You can use the command palette to search for Incremental Writing: related commands:

./images/command-palette_2.png

I use Obsidian Vimrc Support Plugin with the following keybindings:

1
2
3
4
5
6
7
8
exmap IWQueue obcommand obsidian-incremental-writing:load-iw-queue
nmap <Space>iq :IWQueue
exmap IWCurrent obcommand obsidian-incremental-writing:current-iw-repetition
nmap <Space>ic :IWCurrent
exmap IWNext obcommand obsidian-incremental-writing:next-iw-repetition
nmap <Space>in :IWNext
exmap IWDismiss obcommand obsidian-incremental-writing:dismiss-current-repetition
nmap <Space>id :IWDismiss

My video template

./images/template_4.png

If you’re interested, here’s my video template:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
---
<%*
let qcFileName = await tp.system.prompt("Note Title")
titleName = qcFileName
await tp.file.rename(titleName)
await tp.file.move("/Videos/General/" + titleName);
-%>
title: <% qcFileName %>
create: <% tp.file.creation_date("YYYY-MM-DDTHH-mm-ss") %>
status: n
tags: ["todo", ""]
links: [[]]
references:
---

#review

## 🚀 Question/Evidence/Conclusion

Q: <% tp.file.cursor() %>

E: <% tp.file.cursor() %>

C: <% tp.file.cursor() %>

## 💡 Video in 3 Sentences

1. <% tp.file.cursor() %>
2. <% tp.file.cursor() %>
3. <% tp.file.cursor() %>

## 💭 Author's Purpose

<% tp.file.cursor() %>

## ⚡ Personal revelations

> "How my life / behavior / thoughts / ideas have changed because of this video?"

<% tp.file.cursor() %>
Note
<% tp.file.cursor() %> is from Templater Obsidian Plugin where I can use a hotkey to move the cursor.

2. Video source: Local to online

Problem: Local videos taking up too much disk space

I used to use the following command:

1
2
# replace `YourPlayList` with your unlisted playlist identifier.
yt-dlp --get-id "https://www.youtube.com/playlist?list=YourPlayList" | xargs -I '{}' -P 5 yt-dlp --yes-playlist -o '~/Videos/%(title)s.%(ext)s' -f 'bv*[height<=1200]+ba/b[width<2000] / wv*+ba/w' 'https://youtube.com/watch?v={}' --downloader aria2c

It downloads all the videos in my playlist so that could watch them offline. Then in my Obsidian video note I have the following to open the local video file with mpv:

1
mpv ~/Videos/pending/"Cassandra in 100 Seconds.webm"

One issue is that my local video collection had grown up to more than 100GB. It was taking up too much disk space.

Solution: Streaming videos

Requirements: yt-dlp and mpv

1
yt-dlp 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' -o - | mpv -
  1. yt-dlp to direct the video being downloaded to stdout
  2. mpv to open the video

The benefit is that it doesn’t take up any disk space and you can use your mpv config (i.e., save-position-on-quit) and script. However, note that the video is gone forever if it’s taken down or deleted.

Two Tips

1. What if I want to extract all the videos in SuperMemo to Obsidian?

Action plan:

  1. In SuperMemo, export the folder with all the videos as HTML. Clean it up so that you’re left with just the video titles.
  2. Use the following command:
1
ytfzf --auto-select -n 1 -L "video title" | xargs -I {} yt-dlp '{}' -o - | mpv -

We need ytfzf to search for the video id with just the video title.

Note
Nowaways, there are all sorts of emojis and weird symbols in the title. It’s very important to sanitize the video titles when using ytfzf to search for the video. The input for the video title should not contain emojis or the file extension (mp4 or webm), and best with only ASCII characters. If not, you’ll get the wrong video.

2. Batch import videos into Obsidian

For efficiency, I don’t import videos one by one. I have a lot in my pending video queue anyway. For videos I want to watch, I add it to my unlisted playlist. When the list has grown large enough, I’ll imported them into Obsidian.

  1. Grow a txt file with video urls
1
yt-dlp "https://www.youtube.com/playlist?list=PlayListUrl" --get-title --get-id --flat-playlist >> ~/Videos/video-list/pending_videos.txt

This command gets the video title and its id and then append them to pending_videos.txt (note: change the path accordingly). Note that this txt has to be in the following order (i.e., title then video id):

1
2
3
4
What is Incremental Writing? (Obsidian and SuperMemo)
LLS_8Y744lk
AI Assisted Spaced Repetition and Reading
xDPwXBC3oRI
  1. Create all markdown files with the video titles

I’ve written a simple videos_to_md_files program to create markdown files with the above video template containing the video titles.

Note
Make sure you have nodejs installed and the main.js executable.

To run the program, go to its folder, open the terminal and run with nodejs ./main.js

Check out the following in main.js:

1
2
const videoList = "./video_list.txt";
const outputDir = "./output";

They control the input and markdown output. Change them as you see fit. To change the markdown template, look into mdTemplate.js.

./images/nodejs_result.png

Left: video_list.txt content

Right: main.js source

Bottom: terminal output

Conclusion

This is my preference to watch videos. The gist is using some scheduler (be it Incremental Writing Plugin for Obsidian or obsidian-spaced-repetition) to schdule the videos for you. videos_to_md_files is to automate the boring process.