{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "#code\n",
    "from pathlib import Path\n",
    "from pytube import YouTube\n",
    "from pytube import Playlist\n",
    "import moviepy.editor as mp\n",
    "from youtube_transcript_api import YouTubeTranscriptApi\n",
    "from pathvalidate import sanitize_filepath\n",
    "from pytube import cipher\n",
    "import logging\n",
    "import re\n",
    "\n",
    "logger = logging.getLogger(__name__)\n",
    "\n",
    "def get_throttling_function_name(js: str) -> str:\n",
    "    \"\"\"Extract the name of the function that computes the throttling parameter.\n",
    "\n",
    "    :param str js:\n",
    "        The contents of the base.js asset file.\n",
    "    :rtype: str\n",
    "    :returns:\n",
    "        The name of the function used to compute the throttling parameter.\n",
    "    \"\"\"\n",
    "    function_patterns = [\n",
    "        # https://github.com/ytdl-org/youtube-dl/issues/29326#issuecomment-865985377\n",
    "        # https://github.com/yt-dlp/yt-dlp/commit/48416bc4a8f1d5ff07d5977659cb8ece7640dcd8\n",
    "        # var Bpa = [iha];\n",
    "        # ...\n",
    "        # a.C && (b = a.get(\"n\")) && (b = Bpa[0](b), a.set(\"n\", b),\n",
    "        # Bpa.length || iha(\"\")) }};\n",
    "        # In the above case, `iha` is the relevant function name\n",
    "        r'a\\.[a-zA-Z]\\s*&&\\s*\\([a-z]\\s*=\\s*a\\.get\\(\"n\"\\)\\)\\s*&&\\s*'\n",
    "        r'\\([a-z]\\s*=\\s*([a-zA-Z0-9$]+)(\\[\\d+\\])?\\([a-z]\\)',\n",
    "        r'\\([a-z]\\s*=\\s*([a-zA-Z0-9$]+)(\\[\\d+\\])\\([a-z]\\)',\n",
    "    ]\n",
    "    logger.debug('Finding throttling function name')\n",
    "    for pattern in function_patterns:\n",
    "        regex = re.compile(pattern)\n",
    "        function_match = regex.search(js)\n",
    "        if function_match:\n",
    "            logger.debug(\"finished regex search, matched: %s\", pattern)\n",
    "            if len(function_match.groups()) == 1:\n",
    "                return function_match.group(1)\n",
    "            idx = function_match.group(2)\n",
    "            if idx:\n",
    "                idx = idx.strip(\"[]\")\n",
    "                array = re.search(\n",
    "                    r'var {nfunc}\\s*=\\s*(\\[.+?\\]);'.format(\n",
    "                        nfunc=re.escape(function_match.group(1))),\n",
    "                    js\n",
    "                )\n",
    "                if array:\n",
    "                    array = array.group(1).strip(\"[]\").split(\",\")\n",
    "                    array = [x.strip() for x in array]\n",
    "                    return array[int(idx)]\n",
    "\n",
    "    raise RegexMatchError(\n",
    "        caller=\"get_throttling_function_name\", pattern=\"multiple\"\n",
    "    )\n",
    "\n",
    "cipher.get_throttling_function_name = get_throttling_function_name\n",
    "\n",
    "def convert_mp4_to_mp3(file,oppath):\n",
    "    try:\n",
    "    # Load the video file\n",
    "        #video = mp.VideoFileClip(file)\n",
    "        audio=mp.AudioFileClip(str(file))\n",
    "        stem=str(file.stem)#.replace.rstrip().lstrip()\n",
    "\n",
    "        oppath=oppath/'mp3'\n",
    "        oppath.mkdir(parents=True,exist_ok=True)\n",
    "        audio_path=sanitize_filepath(oppath/f'{stem}.mp3')\n",
    "        print('audio_path', stem, audio_path)\n",
    "\n",
    "        # Extract the audio from the video and save it as an MP3 file\n",
    "        #video.audio.write_audiofile(audio_path, codec='pcm_s16le')\n",
    "        audio.write_audiofile(str(audio_path),write_logfile=True,verbose=True)#, codec='pcm_s16le')\n",
    "\n",
    "        # Print a success message\n",
    "        print(f\"Audio extracted and saved as: {audio_path}\")\n",
    "    except Exception as e:\n",
    "        print(f\"Error converting MP4 to MP3: {e}\")\n",
    "\n",
    "def convert_mp4_to_wav(file,oppath):\n",
    "    try:\n",
    "    # Load the video file\n",
    "        #video = mp.VideoFileClip(file)\n",
    "        audio=mp.AudioFileClip(str(file))\n",
    "        stem=str(file.stem)#.replace.rstrip().lstrip()\n",
    "        oppath=oppath/'wav'\n",
    "        oppath.mkdir(parents=True,exist_ok=True)\n",
    "\n",
    "        audio_path=sanitize_filepath(oppath/f'{stem}.wav')\n",
    "        print('audio_path', stem, audio_path)\n",
    "        # Extract the audio from the video and save it as an MP3 file\n",
    "        #video.audio.write_audiofile(audio_path, codec='pcm_s16le')\n",
    "        audio.write_audiofile(str(audio_path),codec='pcm_s16le',write_logfile=False,verbose=True)#, codec='pcm_s16le')\n",
    "\n",
    "        # Print a success message\n",
    "        print(f\"Audio extracted and saved as: {audio_path}\")\n",
    "    except Exception as e:\n",
    "        print(f\"Error converting MP4 to MP3: {e}\")\n",
    "\n",
    "def download_mp4(name,video_url,oppath):\n",
    "    # Get the YouTube object\n",
    "    yt = YouTube(video_url)\n",
    "\n",
    "    # Get video title and language\n",
    "    try:\n",
    "        title = name #yt.title\n",
    "    except Exception as e:\n",
    "        print(e)\n",
    "        title=name\n",
    "   \n",
    "\n",
    "    video_stream = yt.streams.filter(adaptive=True).order_by('abr')\n",
    "   # print(video_stream)\n",
    "    fname=sanitize_filepath(oppath/ f'{title}.mp4')\n",
    "    video_stream.last().download(filename=oppath/ f'{title}.mp4')\n",
    "    return fname \n",
    "\n",
    "def download_songlist(songs,oppath):\n",
    "    \n",
    "    for name,url in songs.items():\n",
    "        try:\n",
    "            file=download_mp4(name,url,oppath)\n",
    "            convert_mp4_to_mp3(file,oppath)\n",
    "        except Exception as e:\n",
    "            print(f\"Error downloading file: {e}\")\n",
    "            continue\n",
    "\n",
    "def download_playlist(url_playlist,oppath):\n",
    "    playlist = Playlist(url_playlist)\n",
    "    ls=[]\n",
    "    for urls in playlist.video_urls:\n",
    "        ls.append(urls)\n",
    "\n",
    "    download_songlist(ls,oppath)\n",
    "    return "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## song list 2024-06-24\n",
    "\n",
    "-   [Sabrina Carpenter - Please Please Please (Lyric Video)](https://www.youtube.com/watch?v=Yl_thbk40A0)\n",
    "-   [Sabrina Carpenter - Espresso (Lyrics)](https://www.youtube.com/watch?v=kVC3BSBm2Dc)\n",
    "-   [Kaash Paige - Love Songs (Lyrics)](https://www.youtube.com/watch?v=7P4q7Oo67-U)\n",
    "-   [L’AMOUR DE MA VIE (Lyrics)](https://www.youtube.com/watch?v=RhGaivzNHps)\n",
    "-   [SZA Greatest Hits Full Album 2024](https://www.youtube.com/watch?v=W6kc4k4NmWQ)\n",
    "-   [Eminem - Just Lose It (Official Music Video)](https://www.youtube.com/watch?v=9dcVOmEQzKA)\n",
    "-   [Rihanna New Playlist 2023](https://www.youtube.com/watch?v=5o9AQs4GOeA)\n",
    "-   [Eminem - Houdini (Perfectly Clean)](https://www.youtube.com/watch?v=YMwWZXQ9xQU)\n",
    "-   [Tyla - Water (Lyrics)](https://www.youtube.com/watch?v=A81ZfezsLcM)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Error downloading file: HTTP Error 400: Bad Request\n",
      "audio_path Sabrina Carpenter - Espresso (Lyrics) /home/ys/Music/Miri/7_playlist/mp3/Sabrina Carpenter - Espresso (Lyrics).mp3\n",
      "MoviePy - Writing audio in /home/ys/Music/Miri/7_playlist/mp3/Sabrina Carpenter - Espresso (Lyrics).mp3\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                      "
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MoviePy - Done.\n",
      "Audio extracted and saved as: /home/ys/Music/Miri/7_playlist/mp3/Sabrina Carpenter - Espresso (Lyrics).mp3\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\r"
     ]
    }
   ],
   "source": [
    "oppath=Path('/home/ys/Music/Miri/7_playlist')\n",
    "\n",
    "list_20240624=['https://www.youtube.com/watch?v=Yl_thbk40A0',\n",
    "'https://www.youtube.com/watch?v=kVC3BSBm2Dc',\n",
    "'https://www.youtube.com/watch?v=7P4q7Oo67-U',\n",
    "'https://www.youtube.com/watch?v=RhGaivzNHps',\n",
    "'https://www.youtube.com/watch?v=W6kc4k4NmWQ',\n",
    "'https://www.youtube.com/watch?v=9dcVOmEQzKA',\n",
    "'https://www.youtube.com/watch?v=5o9AQs4GOeA',\n",
    "'https://www.youtube.com/watch?v=YMwWZXQ9xQU',\n",
    "'https://www.youtube.com/watch?v=A81ZfezsLcM']\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "list_20240624\n",
    "download_songlist(list_20240624,oppath)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## song list 2024-10-05\n",
    "\n",
    "- [sza playlist 1](https://youtu.be/455TWGwAObA?si=GZVF3c86L57d8MsF)\n",
    "- [sza playlist 2](https://youtu.be/IlnxfwtCqLU?si=TjdWp9QbSG2LM2E9) #did not download\n",
    "- [travis scott clean](https://youtu.be/7tcYOY50yXg?si=2zYcfSbta9WhTzGd)\n",
    "- [rihanna playlist](https://youtu.be/5o9AQs4GOeA?si=I0YLFJQl0YwEx9AG) #did not download\n",
    "- [weekend playlist](https://youtu.be/mPXBHFFUgzw?si=g4fhhhza2COvSnLZ) #did not download\n",
    "- [travis scott clean 2](https://youtu.be/JPo3xwzupbE?si=B32de3hrHuaG283K)\n",
    "- [power is power clean](https://youtu.be/iFwQcBoljoo?si=cXrK5-RDq77rvWmh)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "audio_path sza playlist 1 /home/ys/Music/Miri/8_playlist/mp3/sza playlist 1.mp3\n",
      "MoviePy - Writing audio in /home/ys/Music/Miri/8_playlist/mp3/sza playlist 1.mp3\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                          \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MoviePy - Done.\n",
      "Audio extracted and saved as: /home/ys/Music/Miri/8_playlist/mp3/sza playlist 1.mp3\n",
      "Error downloading file: HTTP Error 400: Bad Request\n",
      "audio_path travis scott clean /home/ys/Music/Miri/8_playlist/mp3/travis scott clean.mp3\n",
      "MoviePy - Writing audio in /home/ys/Music/Miri/8_playlist/mp3/travis scott clean.mp3\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                          \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MoviePy - Done.\n",
      "Audio extracted and saved as: /home/ys/Music/Miri/8_playlist/mp3/travis scott clean.mp3\n",
      "audio_path rihanna playlist /home/ys/Music/Miri/8_playlist/mp3/rihanna playlist.mp3\n",
      "MoviePy - Writing audio in /home/ys/Music/Miri/8_playlist/mp3/rihanna playlist.mp3\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                          \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MoviePy - Done.\n",
      "Audio extracted and saved as: /home/ys/Music/Miri/8_playlist/mp3/rihanna playlist.mp3\n",
      "Error downloading file: HTTP Error 400: Bad Request\n",
      "audio_path travis scott clean 2 /home/ys/Music/Miri/8_playlist/mp3/travis scott clean 2.mp3\n",
      "MoviePy - Writing audio in /home/ys/Music/Miri/8_playlist/mp3/travis scott clean 2.mp3\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                      \r"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MoviePy - Done.\n",
      "Audio extracted and saved as: /home/ys/Music/Miri/8_playlist/mp3/travis scott clean 2.mp3\n",
      "Error downloading file: HTTP Error 400: Bad Request\n"
     ]
    }
   ],
   "source": [
    "oppath=Path('/home/ys/Music/Miri/8_playlist')\n",
    "oppath.mkdir(parents=True,exist_ok=True)\n",
    "\n",
    "\n",
    "dict_20241005={\n",
    "'sza playlist 1':r'https://youtu.be/455TWGwAObA?si=GZVF3c86L57d8MsF',\n",
    "'sza playlist 2':r'https://youtu.be/IlnxfwtCqLU?si=TjdWp9QbSG2LM2E9',\n",
    "'travis scott clean':r'https://youtu.be/7tcYOY50yXg?si=2zYcfSbta9WhTzGd',\n",
    "'rihanna playlist':r'https://youtu.be/5o9AQs4GOeA?si=I0YLFJQl0YwEx9AG)',\n",
    "'weekend playlist':r'https://youtu.be/mPXBHFFUgzw?si=g4fhhhza2COvSnLZ',\n",
    "'travis scott clean 2':r'https://youtu.be/JPo3xwzupbE?si=B32de3hrHuaG283K',\n",
    "'power is power clean':r'https://youtu.be/iFwQcBoljoo?si=cXrK5-RDq77rvWmh'\n",
    "}\n",
    "\n",
    "\n",
    "\n",
    "download_songlist(dict_20241005,oppath)\n"
   ]
  },
  {
   "attachments": {
    "image.png": {
     "image/png": "[encoded data, 574728 characters]"
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "https://www.fatpick.com/blog?in=music-theory\n",
    "\n",
    "![image.png](attachment:image.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using preset Guitar Nylon X for guitar nylon\n"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "#for i in range(40,88,1):\n",
    "#    guitar.play_note(i,1,0.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "NOTES_FLAT = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B']\n",
    "NOTES_SHARP = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']\n",
    "NOTES_FLAT=[str.lower(_) for _ in NOTES_FLAT]\n",
    "NOTES_SHARP=[str.lower(_) for _ in NOTES_SHARP]\n",
    "#def NoteToMidi_guitar(string, fret):\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from itertools import product\n",
    "def NoteToMidi(KeyOctave): \n",
    "    # KeyOctave is formatted like 'C#3'\n",
    "    key = KeyOctave[:-1]  # eg C, Db\n",
    "    octave = KeyOctave[-1]   # eg 3, 4\n",
    "    answer = -1\n",
    "    \n",
    "    try:\n",
    "        if 'b' in key:\n",
    "            pos = NOTES_FLAT.index(key)\n",
    "        else:\n",
    "            pos = NOTES_SHARP.index(key)\n",
    "    except:\n",
    "        print('The key is not valid', key)\n",
    "        return answer\n",
    "\n",
    "    answer += pos + 12 * (int(octave) + 1) + 1\n",
    "    return answer\n",
    "\n",
    "def guitarToMidi(string,fret):\n",
    "    openstr={}\n",
    "    openstr[6]=40\n",
    "    openstr[5]=45\n",
    "    openstr[4]=50\n",
    "    openstr[3]=55\n",
    "    openstr[2]=59\n",
    "    openstr[1]=64\n",
    "    midi=openstr[string]+fret\n",
    "    notes=miditoGuitarNote_sharps.loc[midi,0]\n",
    "    notef=miditoGuitarNote_flats.loc[midi,0]\n",
    "    return midi,notes,notef\n",
    "\n",
    "\n",
    "miditoGuitarNote_sharps=(pd.concat([pd.Series({NoteToMidi(f'{k}{o}'):f'{k}{o}' for o,k in product(range(0,7,1),NOTES_SHARP)}),\n",
    "    ], axis=1\n",
    "    )\n",
    "    .assign(E=lambda df: np.where((df.index>=40) & (df.index<59),df[0],0),\n",
    "            A=lambda df: np.where((df.index>=45) & (df.index<64),df[0],0),\n",
    "            D=lambda df: np.where((df.index>=50) & (df.index<69),df[0],0),\n",
    "            G=lambda df: np.where((df.index>=55) & (df.index<74),df[0],0),\n",
    "            B=lambda df: np.where((df.index>=59) & (df.index<78),df[0],0),\n",
    "            e=lambda df: np.where((df.index>=64) & (df.index<83),df[0],0),\n",
    "            )\n",
    ")\n",
    "\n",
    "miditoGuitarNote_flats=(pd.concat([pd.Series({NoteToMidi(f'{k}{o}'):f'{k}{o}' for o,k in product(range(0,7,1),NOTES_FLAT)}),\n",
    "    ], axis=1\n",
    "    )\n",
    "    .assign(E=lambda df: np.where((df.index>=40) & (df.index<59),df[0],0),\n",
    "            A=lambda df: np.where((df.index>=45) & (df.index<64),df[0],0),\n",
    "            D=lambda df: np.where((df.index>=50) & (df.index<69),df[0],0),\n",
    "            G=lambda df: np.where((df.index>=55) & (df.index<74),df[0],0),\n",
    "            B=lambda df: np.where((df.index>=59) & (df.index<78),df[0],0),\n",
    "            e=lambda df: np.where((df.index>=64) & (df.index<83),df[0],0),\n",
    "            )\n",
    ")\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using preset Guitar Nylon X for guitar nylon\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#guitarToMidi(6,2)[0]\n",
    "\n",
    "\n",
    "\n",
    "from scamp import *\n",
    "\n",
    "s= Session() # (temp=100,)\n",
    "#s.print_default_soundfont_presets()\n",
    "guitar=s.new_part(\"guitar nylon\")\n",
    "\n",
    "#https://www.fatpick.com/blog/note-table\n",
    "#http://scamp.marcevanstein.com/narrative/tutorial_videos.html\n",
    "\n",
    "#\n",
    "count=0\n",
    "vol=0\n",
    "#guitar.play_note(guitarToMidi(6,0)[0],1,5,blocking=False)\n",
    "for string in reversed(range(1,7,1)):\n",
    "    for fret in range(0,5):\n",
    "        \n",
    "        if (count%3==0):\n",
    "            vol=1\n",
    "        else:\n",
    "            vol=0.7\n",
    "        count+=1\n",
    "        \n",
    "        guitar.play_note(guitarToMidi(string,fret)[0],vol,0.1)\n",
    "#guitar.play_note(40,1,2)\n",
    "#guitar.play_note(83,1,2)\n",
    "#guitar.play_chord([70,73,83],1,2)\n",
    "#guitar.play_note(52,1,5)\n",
    "s.beat_length"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "import abjad\n",
    "string = \"c'16 f' g' a' d' g' a' b' e' a' b' c'' f' b' c'' d''16\"\n",
    "voice_1 = abjad.Voice(string, name=\"Voice_1\")\n",
    "staff_1 = abjad.Staff([voice_1], name=\"Staff_1\")\n",
    "abjad.show(staff_1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "General",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.2"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
