【無料】いろんなサイトの動画・音楽をダウンロードするアプリ作ったよ(python)

【無料】いろんなサイトの動画・音楽をダウンロードするアプリ作ったよ(python)

今回はpythonを使った動画・音楽をダウンロードする仕組みを作ってみました。

環境

OSmac OS Catalina 10.15
Python3.7.3
subprocess標準ライブラリ
Kivy1.11.1
japanese-kivy0.1.1
youtube-dl2019.9.12.1

仮想空間を作ってKivy, japanese-kivy, youtube-dlをpipでインストールしました。

Kivy

Kivy - Open source Python library for rapid development of applications that make use of innovative user interfaces, such as multi-touch apps.

https://kivy.org/#home

結局何かというと、アプリケーションを作るために使うPythonのオープンソースライブラリだということです。

japanese-kivy

フォントをダウンロードする方法もありますが、今回はimportのみのjapanese-kivyを使いました。

youtube-dl

youtube-dlはコマンドラインから動画をダウンロードできるPythonのライブラリです。

なんと2019/10/22時点で対応サイトが1160サイトにのぼります。

コード

getia.py

getia.py
import japanize_kivy # 日本語設定
import subprocess # pythonからコマンドを操作
import youtube_dl # 一番大切なもの

from kivy.app import App # 必須
from kivy.uix.boxlayout import BoxLayout # アプリのレイアウトに必要
from kivy.uix.textinput import TextInput # テキスト入力に必要
from kivy.uix.recycleview import RecycleView # リスト表示に必要
from kivy.uix.widget import Widget # 必須
from kivy.uix.spinner import Spinner # ドロップダウンメニュー

class GetiaWidget(Widget):
  def reset(self): 
    self.ids.url.text = '' 
    self.ids.status.text = 'status:'     
    self.ids.url_lists.data = [{'text': ""}] 
    self.ids.service.text = 'YouTube'
    self.ids.search_url.text = '' 
    self.ids.download_code.text = '' 
    self.ids.save_place.text = "%(title)s.%(ext)s" 
    self.ids.format_type.text = '' 
    self.ids.checkbox.active = False

  def buttonClicked1(self): 
    try: 
      text = self.ids.search_url.text
      self.ids.url.text = text
      service =  self.ids.service.text 
      format_list = subprocess.check_output("youtube-dl {} --list-format".format(text), shell=True).splitlines() 
      lists = [] 
      for i in format_list: 
        str_i = i.decode("utf-8")
        if service == 'YouTube': 
          if str.isdigit(str_i[0:3]) == True: 
            if str_i[24:34] == "audio only":
              lists.append({'text': "MUSIC: " + str_i[0:3] + " | " + str_i[13:17] + " | " + str_i[41:45]})
            else:
              lists.append({'text': "VIDEO: " + str_i[0:3] + " | " + str_i[13:17] + " | " + str_i[24:34]}) 
        elif service == 'ニコニコ動画': 
          if str.isdigit(str_i[1:4]) == True: 
            lists.append({'text': str_i[0:25] + " | " + str_i[27:30] + " | " + str_i[37:47]}) 
        else: 
          lists.append({'text': str_i}) 
      self.ids.url_lists.data = lists 
      self.ids.status.text = 'status: OK' 
    except: 
      self.ids.status.text = 'status: ERROR' 

  def buttonClicked2(self): 
    url = self.ids.url.text 
    download_code = self.ids.download_code.text 
    save_place = self.ids.save_place.text 
    checkbox = self.ids.checkbox.active 
    format_type = self.ids.format_type.text 
    try:
      if checkbox == True: 
        subprocess.check_output("youtube-dl {} --format {} --output '{}' --merge-output-format {}".format(url, download_code, save_place, format_type), shell=True) 
      else: 
        subprocess.check_output("youtube-dl {} --format {} --output '{}'".format(url, download_code, save_place), shell=True)
      self.ids.status.text = 'status: OK' 
    except: self.ids.status.text = 'status: ERROR'

class getiaApp(App):
  def init(self, kwargs): 
    super(getiaApp, self).init(kwargs)
    self.title = 'GETIA'

  def build(self): 
    return GetiaWidget()
if name == 'main':
  getiaApp().run()

getia.kv

getia.kv
###:kivy
:
  BoxLayout:
    size: root.size #重要!!!
    BoxLayout:
      orientation: 'vertical'#水平
      ActionBar:
        ActionView:
          ActionPrevious:
            title: "GETIA"
            with_previous: False
          ActionButton:
            text: "リセット"
            on_press: root.reset()
      BoxLayout:
         size_hint_y: 0.05 #y1
                  Label:
                    size_hint_x: 0.2 #y1x1
                    font_size: 68
           text: "①"
         Spinner:
           size_hint_x: 0.2 #y1x2
           text: 'YouTube'
           values: 'YouTube', 'ニコニコ動画', 'その他'
           id: service
         TextInput:
           size_hint_x: 0.5 #y1x3
           id: search_url
         Button:
           size_hint_x: 0.1 #y1x4
           text: "検索"
           on_press: root.buttonClicked1()
       BoxLayout:
         size_hint_y: 0.7 #y2
         Label:
           size_hint_x: 0.2 #y2x1
           font_size: 68
           text: "②"
         BoxLayout:
           size_hint_x: 0.8 #y2x2
           orientation: 'vertical'#水平
         Label:
           size_hint_y: 0.3 #y2x2y1
           id: url
           text: 'url'
         RecycleView:
           size_hint_y: 0.7 #y2x2y2
           id: url_lists
           viewclass: 'Label'
           RecycleBoxLayout:
             default_size: None, dp(56)
             default_size_hint: 1, None
             size_hint_y: None
             height: self.minimum_height
             orientation: 'vertical'
      BoxLayout:
        size_hint_y: 0.15 #y3
        Label:
          size_hint_x: 0.2 #y3x1
          font_size: 68
          text: "③"
        BoxLayout:
          size_hint_x: 0.6 #y3x2
          orientation: 'vertical'#水平
          BoxLayout:
            Label:
              size_hint_x: 0.8 #y3x2y1x1
              text: "使う数字入力('動画'+ '音楽'),('動画'),('音楽')"
           TextInput:
             size_hint_x: 0.2 #y3x2y1x2
             id: download_code
          BoxLayout:
            Label:
              size_hint_x: 0.4 #y3x2y2x1
              text: '写真とビデオを合体'
            CheckBox:
              size_hint_x: 0.1 #y3x2y2x2
              id: checkbox
              active: False
            Label:
              size_hint_x: 0.3 #y3x2y2x3
              text: 'ビデオのタイプ'
            TextInput:
              size_hint_x: 0.2 #y3x2y2x4
              id: format_type
          BoxLayout:
            Label:
              size_hint_x: 0.25 #y3x2y3x1
              text: '保存先'
            TextInput:
              size_hint_x: 0.75 #y3x2y3x2
              id: save_place
              text: "%(title)s.%(ext)s"
        Button:
          size_hint_x: 0.2 #y3x3
          text: "GET!!"
          on_press: root.buttonClicked2()
      BoxLayout:
        size_hint_y: 0.1 #y4
        Label:
         id: status
         text: 'status:'

かなり粗い作りですが、今後に期待ということで。。。

使用方法

Visual Studio Codeなどを使って開いたらこんな感じの画面が出てくると思います。

①のYouTubeとあるところはダウンロードしたいサイトを選択できます。とりあえずYoutubeとニコニコ動画、それ以外はその他としてください。

空白のところにダウンロードしたいURLを入力してください。

検索を押すと②のところにいろいろ出てきます。
その際に一番したのところがstatus: OKとなっているか確認してください。

その後、③の一番上の空白にダウンロードしたいものの数字を入力してください。その後GETを押してください。成功すればstatus: OKのままです。

ダウンロード名は「動画のタイトル.フォーマット」となります。

ダウンロード先はファイルがあるところになります。変更したい場合はパスを入力すればいいです。

失敗しているとstatus: ERRORになります。大抵はURLが変だったりします。

もし、動画・音楽を一緒に合わせてダウンロードしたい場合は、「写真とビデオを合体」にチェックをいれ、ビデオのタイプを指定すれば同時にダウンロードできます。

関連記事

【簡単】pythonコードをwordpressに埋め込み・実行・編集までできるツール

【簡単】pythonコードをwordpressに埋め込み・実行・編集までできるツール

【Python】venv仮想環境を2ステップで作成・有効化する

【Python】venv仮想環境を2ステップで作成・有効化する

【失敗談アリ】テックアカデミーのAIコースを徹底レビューする

【失敗談アリ】テックアカデミーのAIコースを徹底レビューする

Javascript/Typescript(+react等)開発環境を簡単に構築するスクリプト作った

Javascript/Typescript(+react等)開発環境を簡単に構築するスクリプト作った