player.Player.download()   A
last analyzed

Complexity

Conditions 4

Size

Total Lines 21
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 19
nop 2
dl 0
loc 21
rs 9.45
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
#
3
# Copyright © 2020 Quentin Kniep <[email protected]>
4
# Distributed under terms of the MIT license.
5
"""Manages playback through multiple audio players.
6
Currently supports: Spotify, MPV (for YouTube).
7
"""
8
9
import json
10
import os.path
11
import time
12
from threading import Thread
13
14
import ffmpeg_normalize
15
from mpv import MPV
16
import pafy
17
import spotipy
18
19
import config
20
from util import YoutubeWrapper
21
22
23
class Player:
24
    def __init__(self):
25
        self.queue = [['_KhsQ3nn6Kw', 'Wankelmut & Emma Louise - My Head Is A Jungle (MK Remix)', '', True]]
26
        self.current_track = ['vzYYW8V3Ibc', 'Nothing', 'Nothing', False]
27
28
        self.player = MPV(ytdl=True, video=False)
29
        self.youtube = YoutubeWrapper()
30
31
        sp_oauth = spotipy.oauth2.SpotifyOAuth(scope=config.SPOTIPY_SCOPE,
32
                                               cache_path=config.SPOTIPY_CACHE)
33
34
        self.spotify = spotipy.Spotify(auth_manager=sp_oauth)
35
36
        devices = self.spotify.devices()
37
        print(json.dumps(devices, sort_keys=True, indent=4))
38
        device_id = devices['devices'][0]['id']
39
40
        results = self.spotify.search(q='Airwaves', type='track')
41
        print(json.dumps(results['tracks']['items'][0], sort_keys=True, indent=4))
42
        self.spotify.start_playback(device_id, uris=[results['tracks']['items'][0]['uri']])
43
44
    def play_loop(self):
45
        while True:
46
            if not self.queue:
47
                next_track = self.youtube.search(self.current_track[0], 1, recs=True)[0]
48
                self.current_track = next_track
49
                self.play(next_track[0])
50
            else:
51
                if not self.queue[0][3]:  # wait for download to finish
52
                    time.sleep(1)
53
                    continue
54
                self.current_track = self.queue[0]
55
                del self.queue[0]
56
                self.play(self.current_track[0])
57
58
    def download_loop(self):
59
        while True:
60
            for entry in self.queue:
61
                if not entry[3]:
62
                    self.download(entry[0])
63
                    entry[3] = True
64
            time.sleep(1)
65
66
    def download(self, ytid):
67
        video = pafy.new(ytid)
68
        stream = video.getbestaudio()
69
        filename = None
70
        while filename is None:
71
            try:
72
                filename = stream.download(filepath='downloads/'+ytid,
73
                                           quiet=True)
74
            except:
75
                pass
76
        print('DOWNLOADED ' + ytid + ' into ' + filename)
77
78
        if config.ENABLE_VOLUME_NORMALIZATION:
79
            ffmpnorm = ffmpeg_normalize._ffmpeg_normalize.FFmpegNormalize(
80
                audio_codec='libmp3lame', output_format='mp3',
81
                video_disable=True, subtitle_disable=True, target_level=-13)
82
            ffmpnorm.add_media_file('downloads/'+ytid, 'downloads/'+ytid)
83
            ffmpnorm.run_normalization()
84
            print('NORMALIZED ' + ytid)
85
86
        return filename
87
88
    def play(self, ytid):
89
        path = 'downloads/' + ytid
90
        if not os.path.isfile(path):
91
            self.download(ytid)
92
        self.player.play(path)
93
        self.player.wait_for_playback()
94
95
    def run(self):
96
        play_thread = Thread(target=self.play_loop)
97
        play_thread.start()
98
99
        download_thread = Thread(target=self.download_loop)
100
        download_thread.start()
101
102
        pafy.set_api_key(config.YOUTUBE_API_KEY)
103