Skip to content

Instantly share code, notes, and snippets.

@Hattshire
Last active November 14, 2018 04:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hattshire/732d0bc19de3d58952f8286b91fc0005 to your computer and use it in GitHub Desktop.
Save Hattshire/732d0bc19de3d58952f8286b91fc0005 to your computer and use it in GitHub Desktop.
# By Oliver Hattshire
# Licenced under laws of the realm of the Public domain
# Problem? It's your fault
# It only works on Windows you say? Yeah, this was a little script for my brobro, he's still into that thing
#
# Usage:
# - Take your youtube URL and dropit to the desktop
# - A shortcut will be created, drop the shortcut over this script
# - Magically a wav file with the sound of the video will appear on desktop
#
# Advanced usage:
# To use your brobro's computer as a jukebox when he leaves it powered on, just open it and add a video
# through "http://{BROBRO'S.COMPUTER.IPADDRESS.ORNAME}:60100/v/add/{YOUTUBE-VIDEO-ID}" using any device!!
#
# Requirements:
# - Youtube-dl.exe on %PATH% (https://youtube-dl.org/downloads/latest/youtube-dl.exe)
# - ffmpeg.exe on %PATH (https://ffmpeg.zeranoe.com/builds/)
# - ffprobe.exe on %PATH (SAMEASABOVE)
# - [Optionally] mpv.exe and friends on %PATH% (https://mpv.srsfckn.biz/)
import sys
import subprocess
# Opens a internet shortcut ini (name.url) and downloads it's link audio as wav
# - shortcut: the shortcut path
def download_mode(shortcut):
import configparser # For parsing the ini
with open(sys.argv[1]) as urlfile:
file = configparser.ConfigParser()
file.read_file(urlfile)
url=file["InternetShortcut"]["URL"]
subprocess.call(['youtube-dl', '-x', '--audio-format', 'wav', url])
# Creates a simple HTTP server that serves as a playlist and player
# to play playable youtube songs on some good BACKGROUND PLAY (Youtube triggered)
def daemon_mode():
import http.server
from time import sleep
from threading import Thread, Lock
HOST = ""
PORT = 60100
BASE_URL = "https://www.youtube.com/watch?v="
BASE_COMMAND = ["mpv", "--no-video", "--player-operation-mode=cplayer"]
PLAYLIST = []
threadLock = Lock()
# Thread to play things without stopping the server
class player_thread(Thread):
def run(self):
DELAY = 2
# True 'cuz sleepy and don't wanna think anymore
while(True):
active = ""
# Do not collide with anything
threadLock.acquire()
if len(PLAYLIST):
active = PLAYLIST.pop(0)
print("Now playing..." + active)
threadLock.release()
# If there is nothing then why run this?
if not active == "":
command = list(BASE_COMMAND)
command.append(active)
subprocess.call(command)
print("Stopped playing..." + active)
# CPU time is valuable
sleep(DELAY)
# Initialize the monster
player = player_thread()
player.start()
# Do the do-able server (ref from here: https://www.simplifiedpython.net/python-simple-http-server/)
class req_handler(http.server.BaseHTTPRequestHandler):
#TODO: Remove the repetition, its ugly :c
def do_GET(self):
if self.do_get_path("/v/add/"):
self.do_add()
self.do_send_message_now(200, "OK")
elif self.do_get_path("/v/remove/"):
self.do_send_message_now(200, "OK")
elif self.do_get_path("/v/play_now/"):
self.do_send_message_now(200, "OK")
elif self.do_get_path("/v/play_next/"):
self.do_send_message_now(200, "OK")
else:
self.do_send_message_now(404, "Not Found") #'Cuz favicon is deprecated, or it isn't (?
#NOTE: it isn't... yet (grinning-devil-face-here)
def do_get_path(self, path):
if self.path.startswith(path):
self.path = self.path.strip(path)
return True
return False
def do_send_message_now(self, code, msg):
self.send_response(code)
self.end_headers()
self.wfile.write(bytes(msg, 'utf-8'))
# Unncesary junk for future use? Hey! delete it!!
def do_notify(self):
print(PLAYLIST)
return
def do_player_next(self):
return
# More repetition!! noo, my eyes X(
def do_add(self):
PLAYLIST.append(BASE_URL + self.path)
self.do_notify()
def do_remove(self):
PLAYLIST.remove(BASE_URL + self.path)
self.do_notify()
def do_play_next(self):
PLAYLIST.insert(0, BASE_URL + self.path)
self.do_notify()
def do_play_now(self):
self.do_play_next()
self.do_player_next()
# https://docs.python.org/3/library/http.server.html#http.server.BaseHTTPRequestHandler
# Hey Python docs, how do I do a handler correctly if you say "do a do_GET" and then omit
# the send_response and end_headers thing? :/
httpd = http.server.HTTPServer((HOST, PORT), req_handler)
httpd.serve_forever()
# Do the drop logic (when drop ocurrs it gets the file path)
if len(sys.argv) < 2 or "-d" in sys.argv or "--daemon" in sys.argv:
print("Daemon mode!")
daemon_mode()
else:
download_mode(sys.argv[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment