Steven Smith revised this gist . Go to revision
1 file changed, 18 insertions, 10 deletions
song2video.py
| @@ -1,11 +1,11 @@ | |||
| 1 | 1 | #!/usr/bin/env python3 | |
| 2 | - | # A script to generate videos for songs. Modify for given file type | |
| 3 | - | # usage: ./song2video.py [ext] | |
| 4 | - | # ext defaults to mp3 | |
| 2 | + | # A script to generate videos for MP3s | |
| 5 | 3 | from moviepy.editor import * | |
| 4 | + | import numpy as np | |
| 5 | + | from PIL import Image | |
| 6 | 6 | from glob import glob | |
| 7 | - | from mutagen.mp3 import EasyMP3 | |
| 8 | - | import sys | |
| 7 | + | from mutagen.mp3 import MP3 | |
| 8 | + | from io import BytesIO | |
| 9 | 9 | ||
| 10 | 10 | #points | |
| 11 | 11 | ART_TOP_LEFT = (620,45) | |
| @@ -13,10 +13,10 @@ ART_SIZE = (585,585) | |||
| 13 | 13 | TEXT_TOP_LEFT = (85,60) | |
| 14 | 14 | TEXT_SIZE = (510,565) | |
| 15 | 15 | ||
| 16 | - | for fn in sorted(glob("*." + (sys.argv[1] if len(sys.argv) > 1 else "mp3"))): | |
| 17 | - | data = EasyMP3(fn) | |
| 16 | + | for fn in sorted(glob("*.mp3")): | |
| 17 | + | data = MP3(fn) | |
| 18 | 18 | audio = AudioFileClip(fn) | |
| 19 | - | text = TextClip("You are listening to\n\n{title[0]}\n\nBy {artist[0]}\n\nFrom {album[0]}".format(**data), | |
| 19 | + | text = TextClip("You are listening to\n\n{TIT2.text[0]}\n\nBy {TPE1.text[0]}\n\nFrom {TALB.text[0]}".format(**data.tags).encode('utf8'), | |
| 20 | 20 | size=TEXT_SIZE, | |
| 21 | 21 | color="white", | |
| 22 | 22 | font="Corbel", | |
| @@ -24,6 +24,14 @@ for fn in sorted(glob("*." + (sys.argv[1] if len(sys.argv) > 1 else "mp3"))): | |||
| 24 | 24 | fontsize=50, | |
| 25 | 25 | method="caption", | |
| 26 | 26 | align="West").set_position(TEXT_TOP_LEFT).set_duration(audio.duration).set_audio(audio) | |
| 27 | - | cover = ImageClip("cover.jpg").set_position(ART_TOP_LEFT).set_duration(audio.duration).resize(ART_SIZE) | |
| 27 | + | cover_art = [k for k in data.tags.keys() if k[:4] == "APIC"] | |
| 28 | + | if cover_art: | |
| 29 | + | if len(cover_art) != 1: | |
| 30 | + | print("Using {} for cover art".format(cover_art[0])) | |
| 31 | + | img_input = np.asarray( Image.open( BytesIO(data.tags[cover_art[0]].data) ), dtype="int32" ) | |
| 32 | + | else: | |
| 33 | + | print("Using cover.jpg for cover art") | |
| 34 | + | img_input = "cover.jpg" | |
| 35 | + | cover = ImageClip(img_input).set_position(ART_TOP_LEFT).set_duration(audio.duration).resize(ART_SIZE) | |
| 28 | 36 | cvc = CompositeVideoClip([text, cover], size=(1280,720)).set_fps(60) | |
| 29 | - | cvc.write_videofile(fn.replace(".mp3", ".mp4")) | |
| 37 | + | cvc.write_videofile(fn.replace(".mp3", ".mp4")) | |
Steven Smith revised this gist . Go to revision
1 file changed, 4 insertions, 4 deletions
song2video.py
| @@ -1,10 +1,10 @@ | |||
| 1 | 1 | #!/usr/bin/env python3 | |
| 2 | - | # A script to generate videos for songs | |
| 2 | + | # A script to generate videos for songs. Modify for given file type | |
| 3 | 3 | # usage: ./song2video.py [ext] | |
| 4 | 4 | # ext defaults to mp3 | |
| 5 | 5 | from moviepy.editor import * | |
| 6 | 6 | from glob import glob | |
| 7 | - | from mutagen import File | |
| 7 | + | from mutagen.mp3 import EasyMP3 | |
| 8 | 8 | import sys | |
| 9 | 9 | ||
| 10 | 10 | #points | |
| @@ -13,8 +13,8 @@ ART_SIZE = (585,585) | |||
| 13 | 13 | TEXT_TOP_LEFT = (85,60) | |
| 14 | 14 | TEXT_SIZE = (510,565) | |
| 15 | 15 | ||
| 16 | - | for fn in glob("*." + (sys.argv[1] if len(sys.argv) > 1 else "mp3")): | |
| 17 | - | data = File(fn) | |
| 16 | + | for fn in sorted(glob("*." + (sys.argv[1] if len(sys.argv) > 1 else "mp3"))): | |
| 17 | + | data = EasyMP3(fn) | |
| 18 | 18 | audio = AudioFileClip(fn) | |
| 19 | 19 | text = TextClip("You are listening to\n\n{title[0]}\n\nBy {artist[0]}\n\nFrom {album[0]}".format(**data), | |
| 20 | 20 | size=TEXT_SIZE, | |
Steven Smith revised this gist . Go to revision
1 file changed, 1 insertion, 1 deletion
song2video.py
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | from moviepy.editor import * | |
| 6 | 6 | from glob import glob | |
| 7 | 7 | from mutagen import File | |
| 8 | - | from sys import argv | |
| 8 | + | import sys | |
| 9 | 9 | ||
| 10 | 10 | #points | |
| 11 | 11 | ART_TOP_LEFT = (620,45) | |
Steven Smith revised this gist . Go to revision
No changes
Steven Smith revised this gist . Go to revision
1 file changed, 29 insertions
song2video.py(file created)
| @@ -0,0 +1,29 @@ | |||
| 1 | + | #!/usr/bin/env python3 | |
| 2 | + | # A script to generate videos for songs | |
| 3 | + | # usage: ./song2video.py [ext] | |
| 4 | + | # ext defaults to mp3 | |
| 5 | + | from moviepy.editor import * | |
| 6 | + | from glob import glob | |
| 7 | + | from mutagen import File | |
| 8 | + | from sys import argv | |
| 9 | + | ||
| 10 | + | #points | |
| 11 | + | ART_TOP_LEFT = (620,45) | |
| 12 | + | ART_SIZE = (585,585) | |
| 13 | + | TEXT_TOP_LEFT = (85,60) | |
| 14 | + | TEXT_SIZE = (510,565) | |
| 15 | + | ||
| 16 | + | for fn in glob("*." + (sys.argv[1] if len(sys.argv) > 1 else "mp3")): | |
| 17 | + | data = File(fn) | |
| 18 | + | audio = AudioFileClip(fn) | |
| 19 | + | text = TextClip("You are listening to\n\n{title[0]}\n\nBy {artist[0]}\n\nFrom {album[0]}".format(**data), | |
| 20 | + | size=TEXT_SIZE, | |
| 21 | + | color="white", | |
| 22 | + | font="Corbel", | |
| 23 | + | kerning=5, | |
| 24 | + | fontsize=50, | |
| 25 | + | method="caption", | |
| 26 | + | align="West").set_position(TEXT_TOP_LEFT).set_duration(audio.duration).set_audio(audio) | |
| 27 | + | cover = ImageClip("cover.jpg").set_position(ART_TOP_LEFT).set_duration(audio.duration).resize(ART_SIZE) | |
| 28 | + | cvc = CompositeVideoClip([text, cover], size=(1280,720)).set_fps(60) | |
| 29 | + | cvc.write_videofile(fn.replace(".mp3", ".mp4")) | |