Weekend project: Build automated YouTube Channels

May 10, 2017

You can’t miss it. Today, the trend on YouTube is for static music videos with beautiful girls or photos, with the channel logo upfront.

The trend on YouTube

I wanted to see if it was possible to create this kind of channel, fully automated with just a Python script.

The first step is to find a music source.

I wanted to find tracks not yet popular on YouTube but with a clear public interest.

I settled on the “Popular Now” playlist on Hype Machine. This was perfect as HypeMachine already as an API, so no need to go scrape the website.

Popular now on HypeMachine

Then, I needed elements to create the static image associated with the music.

For the background image, Unplash was the obvious choice. I created a collection of ~200 images that would fit for the videos. I would then only need to fetch a random one with https://source.unsplash.com/collection/<collectionid>/1920x1080.

Unsplash pictures

I also needed my logo to be put on each video, so I made a quick one.

Unsplash pictures

Here is what it would like at the end, after a quick merge:

Unsplash pictures

Neat right?

I then created a folder for every channel I wanted to automate. This allow me to easily add more channels, in less than 5 minutes.

The main folder

creds.json contains the channel’s oAuth token needed to upload videos to YouTube.

info.json is a very simple file containing some needed infos for the script:

{
  "name": "Chill Ocean",
  "image": "https://source.unsplash.com/collection/<someid>/1920x1080",
  "hypem": [
    "https://api.hypem.com/v2/popular?mode=now&count=10"
  ]
}

Finnaly, res/titlelayer.png is the channel’s logo to be merged.

Now the Python script.

I decided to use MoviePy to build the video, and youtube-upload to send it to YouTube.

from termcolor import colored
from moviepy.editor import *
import json, requests, urllib, os, sys, os.path

reload(sys)
sys.setdefaultencoding("utf-8")

def createVideo(channel, image, title, artist, itemid, audio_url):

	uploaded_location = "/home/vince/Dropbox/Applications/"+channel+"/uploaded.txt"

	name = artist+' - '+title
	
	# Check in the synced text file if we already uploaded this song
	if itemid in open(uploaded_location).read():
		print name + colored(" -> Already uploaded", 'green')
		return
	else:
		print name + colored(" -> Let's upload", 'magenta')

	try:
	
		print 'Downloading audio...'
		urllib.urlretrieve(audio_url, 'temp_files/'+itemid+".mp3")

		print 'Downloading and merging images...'

		urllib.urlretrieve(image, "temp_files/image.jpg")

		audio = AudioFileClip("temp_files/"+itemid+".mp3")

		imageTitle = ImageClip(channel+'/res/titlelayer.png')
		background = ImageClip('temp_files/image.jpg').set_audio(audio)

		# Merge background and logo
		video = CompositeVideoClip([background, imageTitle]) 

		# Save a frame for thumbnail
		video.save_frame('temp_files/'+itemid+'.jpg') 

		# Export the video
		video.set_duration(audio.duration).write_videofile("temp_files/"+itemid+".mp4",fps=1) 

		# Remove the mp3
		os.system('rm temp_files/'+itemid+'.mp3')
		
		# Finally upload the video and remove it from disk when over
		yt_command = """youtube-upload 
			--credentials-file="""+channel+"""/creds.json 
			--title=\""""+name+"""\" 
			--description=\""""+title+" by "+artist+"""\" 
			--category=Music --tags='chill, electro, music' 
			--playlist 'Discover new sounds' 
			--thumbnail 'temp_files/"""+itemid+""".jpg' 
			temp_files/"""+itemid+""".mp4 """
			
		os.system(yt_command + "&& rm temp_files/"+itemid+".mp4 &")

		hs = open(uploaded_location,"a")
		hs.write(itemid+'\n')
		hs.close() 	

	except:
		print colored("An error happened, next.", 'red')

# Get all channels sub-folders
for channel in [d for d in os.listdir('.') if os.path.isdir(os.path.join('.', d))]:
	if channel == "temp_files": continue;

	with open(channel+'/info.json') as data_file:    
		channelInfo = json.load(data_file)

	print '----------------------------------'
	print 'Treating channel '+colored(channelInfo['name'], 'blue')
	print '----------------------------------'

	for link in channelInfo['hypem']:
		
		# Parse tracks from the hypemachine links
		r = requests.get(link)
		tracks = json.loads(r.content)

		# For each tracks, create a video and upload it
		for track in tracks:
			createVideo(channel, 
				channelInfo['image'], 
				track['title'].encode('utf-8'), 
				track['artist'].encode('utf-8'), 
				track['itemid'], 
				'https://hypem.com/serve/public/'+track['itemid']
			)

colored("Script over.", 'red')

I wrote the id of the music to a uploaded.txt file located on my Dropbox, so I could use the script on different computers without worrying that a music would be uploaded multiple times.

Then, you can either choose to manually run the script once a day or set up a cron job to do it for ya.

Conclusion

Unfortunately, after a while (6 months) YouTube disabled my channels after a copyright notice, without really explaining what video was the problem.

The first channel I published brought approximately 1000 subscribers and $1/day before it was shutdown, after a few months of full automation.

I would have posted my stats here but I can’t access the dashboard anymore.

I’m now looking to start another channel with royalty-free music, to be free of copyright problems and take it as far as possible.