Last active
April 4, 2024 21:08
-
-
Save guillaumematheron/89f52ffd274ff3ac99f6dc0249bcc331 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Simulate re-watching all your videos from a given date onwards. | |
If part of your youtube history has been deeleted but is still visible from 'my activity', then | |
you can export it using google takeout, and use this script to simulate watching all these videos | |
in order, in a relatively short time. | |
Note that the history will not be backdated. | |
License: CC0 / Public domain | |
""" | |
import hashlib | |
import json | |
import random | |
import os | |
import time | |
from typing import Any, Dict, List | |
import yt_dlp | |
RESUME = "2022-08-17T11:50:00.000Z" | |
def main(): | |
# An empty file will be created in the 'done' directory to keep track | |
# of videos that were already watched, so that this script can be | |
# interrupted and resumed. | |
try: | |
os.makedirs("done") | |
except FileExistsError: | |
pass | |
# This file should be generated using google takeout | |
with open("watch-history.json", encoding="utf8") as f: | |
data = json.load(f) | |
kept: List[Dict[str, Any]] = [] | |
for event in data: | |
# Disregard youtube music | |
if event["header"] != "YouTube": | |
continue | |
if "details" in event and event["details"][0]["name"] == "From Google Ads": | |
continue | |
if event["time"] < RESUME: | |
continue | |
if "titleUrl" not in event: | |
continue | |
kept.append(event) | |
print(f"Found {len(kept)} videos to watch") | |
# Deduplicate | |
kept = [event for event in {event["titleUrl"]: event for event in kept}.values()] | |
print(f"Found {len(kept)} videos to watch after de-duplication") | |
# Sort | |
kept.sort(key=lambda x: x["time"]) | |
opts = { | |
"mark_watched": True, | |
"simulate": True, | |
"quiet": True, | |
"cookiesfrombrowser": ("firefox",), | |
} | |
with yt_dlp.YoutubeDL(opts) as ydl: | |
for i, event in enumerate(kept): | |
t = event["time"] | |
url = event["titleUrl"] | |
title = event["title"][8:] | |
m = hashlib.sha256() | |
m.update(url.encode("utf-8")) | |
marker = "done/" + m.hexdigest() | |
print( | |
f"{i}/{len(kept)} \t {t} \t {url} \t {title} ... ", end="", flush=True | |
) | |
try: | |
with open(marker, "r"): | |
pass | |
print(" -> Already done") | |
continue | |
except FileNotFoundError: | |
pass | |
try: | |
ydl.download(url) | |
print(" -> Sleeping ... ", end="", flush=True) | |
time.sleep(3 + random.random() * 8) | |
print(" -> Done") | |
except yt_dlp.utils.DownloadError: | |
print(" -> DownloadError") | |
with open(marker, "w"): | |
pass | |
if __name__ == "__main__": | |
main() |
Gotcha thanks
Not ideal at all, tried couple dozens of videos and all of them falls into the current date, not the date you have watched.
Yes, as far as I know there is no way to backdate the watch date of videos unfortunately. I'll add a comment making that clear.
an update, the history entries started coming back for a lot of people. It seems mine is mostly fixed.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sure, consider this CC0 or public domain.
The main intended effect was attained for me : watched videos are not suggested anymore. I did not notice it decrease the quality of my recommendations, but I mostly stick to channels I subscribe to so my recommendations are pretty easy to predict.