mckabue commited on
Commit
584c24c
·
1 Parent(s): 6a5bc2f

Read details at

Browse files
Files changed (2) hide show
  1. app.py +7 -2
  2. index.html +28 -15
app.py CHANGED
@@ -1,10 +1,15 @@
1
  """Shazam Playlist to Youtube Playlist"""
2
 
3
  from typing import Optional
 
4
  import pandas as pd
5
  from pytube import Search, YouTube
6
  from flask import Flask, request, send_from_directory
7
 
 
 
 
 
8
  app = Flask(__name__)
9
 
10
  @app.route('/')
@@ -21,7 +26,7 @@ def video_id() -> str:
21
  try:
22
  title: str = request.json.get('title')
23
  artist: str = request.json.get('artist')
24
- youtube: YouTube = _get_youtube_song(title, artist)
25
  return youtube.video_id
26
  except Exception as e:
27
  return str(e)
@@ -38,7 +43,7 @@ def parse_csv():
38
  except Exception as e:
39
  return str(e)
40
 
41
- def _get_youtube_song(title: str, artist: str) -> Optional[YouTube]:
42
  """Searches for a YouTube video based on the given title and artist"""
43
  search_result = Search(f'{title} by {artist}')
44
  return search_result.results[0] if search_result.results else None
 
1
  """Shazam Playlist to Youtube Playlist"""
2
 
3
  from typing import Optional
4
+ import logging
5
  import pandas as pd
6
  from pytube import Search, YouTube
7
  from flask import Flask, request, send_from_directory
8
 
9
+ # https://github.com/pytube/pytube/issues/1270#issuecomment-2100372834
10
+ pytube_logger = logging.getLogger('pytube')
11
+ pytube_logger.setLevel(logging.ERROR)
12
+
13
  app = Flask(__name__)
14
 
15
  @app.route('/')
 
26
  try:
27
  title: str = request.json.get('title')
28
  artist: str = request.json.get('artist')
29
+ youtube: YouTube = get_youtube_song(title, artist)
30
  return youtube.video_id
31
  except Exception as e:
32
  return str(e)
 
43
  except Exception as e:
44
  return str(e)
45
 
46
+ def get_youtube_song(title: str, artist: str) -> Optional[YouTube]:
47
  """Searches for a YouTube video based on the given title and artist"""
48
  search_result = Search(f'{title} by {artist}')
49
  return search_result.results[0] if search_result.results else None
index.html CHANGED
@@ -15,20 +15,19 @@
15
  height: 100%;
16
  }
17
 
18
- .playlist tbody tr {
19
- cursor: pointer;
20
  }
21
  </style>
22
  </head>
23
 
24
  <body>
25
  <div class="container my-4">
26
- <h1 class="text-center">Shazam Playlist to Youtube Playlist</h1>
27
- <em>
28
  <i>
29
- This is an idea from <a href="https://toknow.ai/">ToKnow.ai</a>
30
- <a href="https://toknow.ai/posts/shazam-playlist-to-youtube-playlist/">blog post</a>.
31
- This service is free of charge and does not require any payment or subscription to use.
32
  </i>
33
  </em>
34
  <p class="text-center">
@@ -60,7 +59,8 @@
60
  const playlistTable = document.querySelector('.playlist');
61
  const uploaForm = document.querySelector('.upload-form');
62
  let songsPlaylist = []
63
- let videoIndex = 0;
 
64
 
65
  uploaForm.addEventListener('input', e => {
66
  e.preventDefault();
@@ -87,7 +87,13 @@
87
  }
88
  })
89
  }
90
-
 
 
 
 
 
 
91
  async function getVideoId(song) {
92
  const response = await fetch(
93
  '/video_id',
@@ -99,7 +105,7 @@
99
  return await response.text()
100
  }
101
  async function nextVideo(callback, newIndex = undefined) {
102
- newIndex = (newIndex || (videoIndex + 1))
103
  videoIndex = newIndex < songsPlaylist.length ? newIndex : 0;
104
  let video_id = await getVideoId(songsPlaylist[videoIndex]);
105
  callback(video_id);
@@ -117,7 +123,7 @@
117
  <th>${i.Title}</th>
118
  <th>${i.Artist}</th>
119
  </tr>`
120
- ).join('')
121
  playlistTable.innerHTML = `
122
  <table class="table table-striped table-hover table-bordered rounded">
123
  <thead>
@@ -133,7 +139,6 @@
133
  playlistTable.innerHTML = error;
134
  }
135
  }
136
- let youtubePlayer;
137
  function onYouTubeIframeAPIReady() {
138
  const youtubePlayerElement = document.querySelector('.youtube-player');
139
  youtubePlayer = window.youtubePlayer = new YT.Player(youtubePlayerElement, {
@@ -149,7 +154,8 @@
149
  onContinue(event?.target);
150
  }
151
  },
152
- 'onError': function(event) {
 
153
  onContinue(event?.target);
154
  }
155
  }
@@ -162,13 +168,20 @@
162
  }
163
  }, 500);
164
  };
165
-
166
  function onContinue(player = undefined, newIndex = undefined) {
167
  if (songsPlaylist.length > 0) {
168
  nextVideo((value) => {
169
  player = player || youtubePlayer
170
  player.loadVideoById(value);
171
- player.playVideo();
 
 
 
 
 
 
 
 
172
  }, newIndex);
173
  }
174
  }
 
15
  height: 100%;
16
  }
17
 
18
+ .playlist tbody tr {
19
+ cursor: pointer;
20
  }
21
  </style>
22
  </head>
23
 
24
  <body>
25
  <div class="container my-4">
26
+ <h1 class="text-center">Convert Your Shazam Playlist to YouTube Playlist</h1>
27
+ <em class="text-center">
28
  <i>
29
+ Read details at
30
+ <a href="https://toknow.ai/posts/shazam-playlist-to-youtube-playlist/"><b>ToKnow.ai</b> blog post</a>.
 
31
  </i>
32
  </em>
33
  <p class="text-center">
 
59
  const playlistTable = document.querySelector('.playlist');
60
  const uploaForm = document.querySelector('.upload-form');
61
  let songsPlaylist = []
62
+ let videoIndex = -1;
63
+ let youtubePlayer;
64
 
65
  uploaForm.addEventListener('input', e => {
66
  e.preventDefault();
 
87
  }
88
  })
89
  }
90
+ function addErrorToCurrentIndex() {
91
+ playlistTable.querySelectorAll('tbody tr').forEach(row => {
92
+ if (Number(row.dataset.index) == videoIndex) {
93
+ row.classList.add('bg-danger');
94
+ }
95
+ })
96
+ }
97
  async function getVideoId(song) {
98
  const response = await fetch(
99
  '/video_id',
 
105
  return await response.text()
106
  }
107
  async function nextVideo(callback, newIndex = undefined) {
108
+ newIndex = newIndex >= 0 ? newIndex : (videoIndex + 1)
109
  videoIndex = newIndex < songsPlaylist.length ? newIndex : 0;
110
  let video_id = await getVideoId(songsPlaylist[videoIndex]);
111
  callback(video_id);
 
123
  <th>${i.Title}</th>
124
  <th>${i.Artist}</th>
125
  </tr>`
126
+ ).join('')
127
  playlistTable.innerHTML = `
128
  <table class="table table-striped table-hover table-bordered rounded">
129
  <thead>
 
139
  playlistTable.innerHTML = error;
140
  }
141
  }
 
142
  function onYouTubeIframeAPIReady() {
143
  const youtubePlayerElement = document.querySelector('.youtube-player');
144
  youtubePlayer = window.youtubePlayer = new YT.Player(youtubePlayerElement, {
 
154
  onContinue(event?.target);
155
  }
156
  },
157
+ 'onError': function (event) {
158
+ addErrorToCurrentIndex();
159
  onContinue(event?.target);
160
  }
161
  }
 
168
  }
169
  }, 500);
170
  };
 
171
  function onContinue(player = undefined, newIndex = undefined) {
172
  if (songsPlaylist.length > 0) {
173
  nextVideo((value) => {
174
  player = player || youtubePlayer
175
  player.loadVideoById(value);
176
+ setTimeout(() => {
177
+ player.playVideo();
178
+
179
+ setTimeout(() => {
180
+ if (player.getPlayerState() != YT.PlayerState.PLAYING) {
181
+ player.playVideo();
182
+ }
183
+ }, 10);
184
+ }, 10);
185
  }, newIndex);
186
  }
187
  }