Skip to content

Commit

Permalink
✨ feat: 完成了音乐下载功能
Browse files Browse the repository at this point in the history
  • Loading branch information
nichuanfang committed Oct 10, 2023
1 parent 242a0fd commit 7aac9d4
Show file tree
Hide file tree
Showing 7 changed files with 259 additions and 7 deletions.
1 change: 1 addition & 0 deletions .github/workflows/release_pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# 推送到pypi
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,21 @@ pip install -U music-tool-kit
- 音乐下载

```bash
mtk download 网址 输出 [封面url]
mtk 网址 [输出] [封面url]
```

> tips: 输出格式为 歌曲名[-歌手] 输出歌曲格式为 mp3, 封面 url 可选
> tips: 输出格式为 歌曲名[-歌手] 输出歌曲格式为 mp3 可选, 封面 url 也可选
- 音乐剪辑

```bash
mtk clip 输入的文件 开始时间 结束时间
mtk -clip 输入的文件 开始时间 结束时间
```

> tips: 时间格式为: 00:00:00
- 音乐伴奏提取

```bash
mtk -extract 输入的文件 输出的文件
```
147 changes: 145 additions & 2 deletions mtk/__main__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,145 @@
def main():
print('hello world')
import sys
import requests
from mtk.mp3_util import MP3
from yt_dlp import YoutubeDL

# 提取yt_dlp信息
def extract_info(url):
ydl = YoutubeDL()
info = ydl.extract_info(url, download=False)
return info

def download(url:str,title:str|None=None,cover_url:str|None=None):
"""下载mp3格式的音乐
Args:
url (str): 歌曲网址
name (str): 歌曲[-歌手]
cover_url (str, optional): 封面url. Defaults to None.
"""
if title != None:
outtmpl = f'{title}.%(ext)s'
else:
outtmpl = '%(title)s.%(ext)s'

ydl_opts = {
'quiet': True,
'no_color': True,
'format': 'bestaudio/best',
'outtmpl': outtmpl,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': 0
}],
}
with YoutubeDL(ydl_opts) as ydl:
ydl.download([url])

if title != None:
mp3 = MP3(f'{title}.mp3')
if title.find('-') != -1:
song = title.split('-')[0]
artist = title.split('-')[1]
mp3.add_title(song)
mp3.add_artist(artist)
else:
mp3.add_title(title)
if cover_url != None:
mp3.add_cover(cover_url)
mp3.save()
else:
info = extract_info(url)
title = info['title']
mp3 = MP3(f'{title}.mp3')
mp3.add_title(title)
if cover_url != None:
mp3.add_cover(cover_url)
else:
thumbnail = info['thumbnail']
mp3.add_cover(thumbnail)
mp3.save()

print('下载完成!')

def clip(path:str,start:str,end:str):
"""剪辑音乐
Args:
path (str): 歌曲文件路径
start (str): 开始时间(格式 00:00:00)
end (str): 结束时间(格式 00:00:00)
"""
pass

def main(args=None):
if args == None:
args = sys.argv[1:]
# 校验args
if len(args) == 0:
print('configuration:\n\n'
'---------------------------------------------\n'+
'下载: mtk url [title] [cover_url]\n'+
'剪辑: mtk --clip path start end\n'
'---------------------------------------------\n'
)
return
flag = args[0]
if flag == '--clip':
path = args[1]
start = args[2]
end = args[3]
clip(path,start,end)
elif flag == '-extract':
pass
else:
# 默认下载
# 判断flag是否是网址
if flag.startswith(('http://','https://')):
url = flag
if len(args) == 1:
download(url,None,None)
elif len(args) == 2:
title_or_url = args[1]
if title_or_url.startswith(('http://','https://')):
download(url,None,title_or_url)
else:
download(url,title_or_url,None)
elif (len(args) == 3):
if args[1].startswith(('http://','https://')):
print('歌曲名称不合法!')
return
if not args[2].startswith(('http://','https://')):
print('封面url不合法!')
return
download(url,args[1],args[2])
else:
print('非法参数!')
else:
print('请输入合法的网址!')
return

if __name__ == '__main__':
# add_cover('out.mp3','https://yt3.googleusercontent.com/ytc/APkrFKYi81RwDYPJx9n1cZzI3jT3nQv1PmB0QPlNk2Ruhw=s900-c-k-c0x00ffffff-no-rj')
# add_title('out.mp3','test_title')
# add_artist('out.mp3','test_artist')

# mp3 = MP3('out.mp3')
# mp3.add_cover('https://yt3.googleusercontent.com/ytc/APkrFKYi81RwDYPJx9n1cZzI3jT3nQv1PmB0QPlNk2Ruhw=s900-c-k-c0x00ffffff-no-rj')
# mp3.add_title('test_title')
# mp3.add_artist('test_artist')
# mp3.add_album('test_album')
# mp3.save()


# info = extract_info('https://www.youtube.com/watch?v=zq-lIBwhWLk')
# # 获取缩略图url
# thumbnail = info['thumbnail']
# # 获取标题
# title = info['title']


# download('https://youtu.be/xsk1SLmf9a0?si=zj8z06UGwLAKEMOj','Handbook - See The World','https://i2.cdn.turner.com/cnn/2008/WORLD/asiapcf/09/03/ta.jaychou/art.jaychou.jpg')

pass


98 changes: 98 additions & 0 deletions mtk/mp3_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
import requests
import os
from mutagen.id3 import ID3, APIC, TIT2, TPE1, TALB

def get_image_bytes(image_url):
# 发送HTTP请求,获取图片内容
response = requests.get(image_url)

# 将图片内容转换为字节数据
image_bytes = response.content

return image_bytes

# webp转jpg
def webp2jpg(webp_path,jpg_path):
from PIL import Image
im = Image.open(webp_path).convert('RGB')
im.save(jpg_path, 'jpeg')
# 删除webp文件
os.remove(webp_path)
# 返回jpg文件字节码
with open(jpg_path,'rb') as f:
return f.read()

class MP3:

def __init__(self,mp3path:str) -> None:
"""mp3对象
Args:
mp3path (str): mp3文件路径
"""
try:
self.mp3path = mp3path
self.songFile = ID3(mp3path)
except:
print('mp3路径不存在!')
return

# 给mp3文件添加封面
def add_cover(self,cover_url):
mp3_name = self.mp3path.split('.')[0]
cover_extension = cover_url.split('.')[-1]

response = requests.get(cover_url)
if response.status_code != 200:
print('封面url不合法!')
return
image_data = response.content
if cover_extension == 'webp':
with open(f'{mp3_name}.{cover_extension}','wb') as f:
f.write(response.content)
image_data = webp2jpg(f'{mp3_name}.{cover_extension}',f'{mp3_name}.jpg')
os.remove(f'{mp3_name}.jpg')

# 插入封面
self.songFile['APIC'] = APIC(
encoding=0,
mime='image/jpg',
type=3,
desc=u'Cover',
data=image_data
)
print(f'封面{cover_url}添加完成')

# 给mp3文件添加歌名
def add_title(self,title):
# 插入歌名
self.songFile['TIT2'] = TIT2(
encoding=3,
text=title
)
print(f'歌名{title}添加完成')

# 给mp3文件添加歌手
def add_artist(self,artist):
# 插入歌手
self.songFile['TPE1'] = TPE1(
encoding=3,
text=artist
)
print(f'歌手{artist}添加完成')

# 给mp3文件添加专辑
def add_album(self,album):
# 插入专辑
self.songFile['TALB'] = TALB(
encoding=3,
text=album
)
print(f'专辑{album}添加完成')

def save(self):
# 保存
self.songFile.save()
print('保存完成')

Empty file removed mtk/requirements.txt
Empty file.
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
yt-dlp>=2023.10.7
ffmpeg>=1.4
requests>=2.26.0
mutagen>=1.47.0
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
with open('README.md', 'r', encoding='utf-8') as f:
readme = f.read()

with open('mtk/requirements.txt', 'r', encoding='utf-8') as f:
with open('requirements.txt', 'r', encoding='utf-8') as f:
requirements = f.read()

setup(
name='music-tool-kit',
version='0.0.3',
version='0.0.4',
description='A tool kit for music download and clip',
long_description_content_type='text/markdown',
long_description=readme,
Expand Down

0 comments on commit 7aac9d4

Please sign in to comment.