-
Notifications
You must be signed in to change notification settings - Fork 292
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit fa87f66
Showing
12 changed files
with
455 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import pickle | ||
import os | ||
from google_auth_oauthlib.flow import Flow, InstalledAppFlow | ||
from googleapiclient.discovery import build | ||
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload | ||
from google.auth.transport.requests import Request | ||
|
||
def Create_Service(client_secret_file, api_name, api_version, *scopes): | ||
CLIENT_SECRET_FILE = client_secret_file | ||
API_SERVICE_NAME = api_name | ||
API_VERSION = api_version | ||
SCOPES = [scope for scope in scopes[0]] | ||
print(SCOPES) | ||
|
||
cred = None | ||
|
||
pickle_file = f'token_{API_SERVICE_NAME}_{API_VERSION}.pickle' | ||
# print(pickle_file) | ||
|
||
if os.path.exists(pickle_file): | ||
with open(pickle_file, 'rb') as token: | ||
cred = pickle.load(token) | ||
|
||
if not cred or not cred.valid: | ||
if cred and cred.expired and cred.refresh_token: | ||
cred.refresh(Request()) | ||
else: | ||
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES) | ||
cred = flow.run_local_server() | ||
|
||
with open(pickle_file, 'wb') as token: | ||
pickle.dump(cred, token) | ||
|
||
try: | ||
service = build(API_SERVICE_NAME, API_VERSION, credentials=cred) | ||
print(API_SERVICE_NAME, 'service created successfully') | ||
return service | ||
except Exception as e: | ||
print('Unable to connect.') | ||
print(e) | ||
return None | ||
|
||
def convert_to_RFC_datetime(year=1900, month=1, day=1, hour=0, minute=0): | ||
dt = datetime.datetime(year, month, day, hour, minute, 0).isoformat() + 'Z' | ||
return dt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Fully Automated Youtube Channel | ||
|
||
Code to run a fully automated youtube that can scrape content, edit a compilation, and upload to youtube daily. | ||
|
||
# Instructions | ||
|
||
1. [Download](https://github.com/nathan-149/automated_youtube_channel/archive/main.zip) the Github Repository | ||
|
||
2. Download and install [Python](https://www.python.org/downloads/) and [pip](https://pip.pypa.io/en/stable/installing/) | ||
|
||
3. Run `pip install -r requirements.txt` | ||
|
||
4. Get setup and create a Project with the Youtube API: https://developers.google.com/youtube/v3/quickstart/python | ||
Be sure to follow it carefully, as it won't work if you don't do this part right. | ||
Download your OATH file as "secret.json" in your folder. | ||
|
||
5. Run `python3 setup_google.py` and follow the web page that opens up. | ||
|
||
6. Create an instagram account and follow accounts you want to scrape from | ||
|
||
7. Open main.py in a text editor and fill in necessary information | ||
|
||
8. Run `python3 main.py` | ||
|
||
9. Enjoy your fully automated youtube channel! :) Note that for uploading public videos, you have to complete an audit for the Youtube API. See the note in the [Google Documentation](https://developers.google.com/youtube/v3/docs/videos/insert) |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from datetime import datetime | ||
import instaloader | ||
|
||
# insta loader downloads some posts under the hashtag urbanphotography | ||
|
||
L = instaloader.Instaloader() | ||
|
||
posts = instaloader.Hashtag.from_name(L.context, "urbanphotography").get_posts() | ||
|
||
SINCE = datetime(2020, 5, 10) # further from today, inclusive | ||
UNTIL = datetime(2020, 5, 11) # closer to today, not inclusive | ||
|
||
k = 0 # initiate k | ||
#k_list = [] # uncomment this to tune k | ||
|
||
for post in posts: | ||
postdate = post.date | ||
|
||
if postdate > UNTIL: | ||
continue | ||
elif postdate <= SINCE: | ||
k += 1 | ||
if k == 50: | ||
break | ||
else: | ||
continue | ||
else: | ||
L.download_post(post, "#urbanphotography") | ||
# if you want to tune k, uncomment below to get your k max | ||
#k_list.append(k) | ||
k = 0 # set k to 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from instalooter.looters import ProfileLooter | ||
import datetime | ||
import dateutil.relativedelta | ||
|
||
# instalooter_test downloads videos posted by postleg__ in the last month | ||
|
||
# Instanciate | ||
looter = ProfileLooter("postleg__", videos_only=True, template="{id}-{username}-{width}-{height}") | ||
looter.login("bigshaq6bih", "mmm12345") | ||
|
||
today = datetime.date.today() | ||
thismonth = (today, today - dateutil.relativedelta.relativedelta(days=28)) | ||
|
||
looter.download('./Memes_December_4', media_count=50, timeframe=thismonth) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
from scrape_videos import scrapeVideos | ||
from make_compilation import makeCompilation | ||
from upload_ytvid import uploadYtvid | ||
import schedule | ||
import time | ||
import datetime | ||
import os | ||
import shutil | ||
|
||
# FILL THESE OUT | ||
IG_USERNAME = "chewymemes_v3" | ||
IG_PASSWORD = "mmm12345" | ||
|
||
INTRO_VID = 'intro_vid.mp4' # SET AS '' IF YOU DONT HAVE ONE | ||
OUTRO_VID = '' | ||
TOTAL_VID_LENGTH = 13*60 | ||
MAX_CLIP_LENGTH = 18 | ||
MIN_CLIP_LENGTH = 4 | ||
|
||
num_to_month = { | ||
1: "Jan", | ||
2: "Feb", | ||
3: "Mar", | ||
4: "Apr", | ||
5: "May", | ||
6: "June", | ||
7: "July", | ||
8: "Aug", | ||
9: "Sept", | ||
10: "Oct", | ||
11: "Nov", | ||
12: "Dec" | ||
} | ||
|
||
def routine(): | ||
now = datetime.datetime.now() | ||
print(now.year, now.month, now.day, now.hour, now.minute, now.second) | ||
title = "BEST DANK MEMES COMPILATION V" + str(now.month) + "." + str(now.day) + " (VIDEOS)" | ||
videoDirectory = "/tmp/Memes_" + num_to_month[now.month].upper() + "_" + str(now.year) + "_V" + str(now.day) + "/" | ||
outputFile = "./" + num_to_month[now.month].upper() + "_" + str(now.year) + "_v" + str(now.day) + ".mp4" | ||
metadataFile = "./metadata-" + num_to_month[now.month].upper() + "_" + str(now.year) + "_v" + str(now.day) + ".txt" | ||
description = "" | ||
print(outputFile) | ||
|
||
if not os.path.exists(videoDirectory): | ||
os.makedirs(videoDirectory) | ||
""" | ||
# Step 1: Scrape Videos | ||
print("Scraping Videos...") | ||
scrapeVideos(username = IG_USERNAME, | ||
password = IG_PASSWORD, | ||
output_folder = videoDirectory, | ||
days=1) | ||
print("Scraped Videos!") | ||
""" | ||
f = open(metadataFile, "w") | ||
f.write(title + "\n\n") | ||
description = "Enjoy the memes :) \n\n" \ | ||
"like and subscribe to @Chewy for more \n\n" \ | ||
"The memes in the compilation are reposts from various private instagram meme accounts.\n" \ | ||
"this episode's were from: \n" | ||
f.write(description) | ||
|
||
# Step 2: Make Compilation | ||
print("Making Compilation...") | ||
description += makeCompilation(path = videoDirectory, | ||
introName = INTRO_VID, | ||
outroName = OUTRO_VID, | ||
totalVidLength = TOTAL_VID_LENGTH, | ||
maxClipLength = MAX_CLIP_LENGTH, | ||
minClipLength = MIN_CLIP_LENGTH, | ||
outputFile = outputFile) | ||
print("Made Compilation!") | ||
|
||
description += "\n\nCopyright Disclaimer, Under Section 107 of the Copyright Act 1976, allowance is made for 'fair use' for purposes such as criticism, comment, news reporting, teaching, scholarship, and research. Fair use is a use permitted by copyright statute that might otherwise be infringing. Non-profit, educational or personal use tips the balance in favor of fair use.\n\n" | ||
description += "#memes #dankmemes #compilation #funny #funnyvideos \n\n" | ||
f.write(description + "\n\n") | ||
f.close() | ||
|
||
# Step 3: Upload to Youtube | ||
print("Uploading to Youtube...") | ||
uploadYtvid(VIDEO_FILE_NAME=outputFile, | ||
title=title, | ||
description=description) | ||
print("Uploaded To Youtube!") | ||
|
||
# Step 4: Cleanup | ||
print("Removing temp files!") | ||
# Delete all files made: | ||
# Folder videoDirectory | ||
shutil.rmtree(videoDirectory, ignore_errors=True) | ||
# File outputFile | ||
try: | ||
os.remove(outputFile) | ||
except OSError as e: ## if faile,d, report it back to the user ## | ||
print ("Error: %s - %s." % (e.filename, e.strerror)) | ||
print("Removed temp files!") | ||
|
||
def attemptRoutine(): | ||
try: | ||
routine() | ||
except OSError as err: | ||
print("Routine Failed on " + "OS error: {0}".format(err)) | ||
time.sleep(60*60) | ||
routine() | ||
|
||
attemptRoutine() | ||
schedule.every().day.at("19:05").do(attemptRoutine) | ||
|
||
while True: | ||
schedule.run_pending() | ||
time.sleep(60) # wait one min | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
from moviepy.editor import VideoFileClip, concatenate_videoclips | ||
from moviepy.video.fx.resize import resize | ||
import os | ||
from os.path import isfile, join | ||
import random | ||
import shutil | ||
from collections import defaultdict | ||
|
||
VideoFileClip.resize = resize | ||
|
||
def extractAcc(filepath): | ||
try: | ||
s = filepath.split("/")[-1].split("-") | ||
acc = "-".join(s[1:(2+(len(s) - 4))]) | ||
return acc | ||
except: | ||
return "" | ||
|
||
# generateTimeRange converts float seconds to a range of form @MM:SS | ||
def generateTimeRange(duration, clipDuration): | ||
preHour = int(duration / 60) | ||
preMin = int(duration % 60) | ||
preTime = str(preHour // 10) + str(preHour % 10) + ":" + str(preMin // 10) + str(preMin % 10) | ||
|
||
duration += clipDuration | ||
postHour = int(duration / 60) | ||
postMin = int(duration % 60) | ||
postTime = str(postHour // 10) + str(postHour % 10) + ":" + str(postMin // 10) + str(postMin % 10) | ||
|
||
#return "@" + preTime + " - " + "@" + postTime | ||
return "@" + preTime | ||
|
||
# makeCompilation takes videos in a folder and creates a compilation with max length totalVidLength | ||
def makeCompilation(path = "./", | ||
introName = '', | ||
outroName = '', | ||
totalVidLength = 10*60, | ||
maxClipLength = 20, | ||
minClipLength = 5, | ||
outputFile = "output.mp4"): | ||
|
||
allVideos = [] | ||
seenLengths = defaultdict(list) | ||
totalLength = 0 | ||
for fileName in os.listdir(path): | ||
if isfile(join(path, fileName)) and fileName.endswith(".mp4"): | ||
print(fileName) | ||
filePath = os.path.join(path, fileName) | ||
# Destination path | ||
destination = os.path.join("./Duplicates/", fileName) | ||
clip = VideoFileClip(filePath) | ||
clip = clip.resize(width=1920) | ||
clip = clip.resize(height=1080) | ||
duration = clip.duration | ||
print(duration) | ||
if duration <= maxClipLength and duration >= minClipLength: | ||
allVideos.append(clip) | ||
seenLengths[duration].append(fileName) | ||
totalLength += duration | ||
|
||
print("Total Length: " + str(totalLength)) | ||
for length in seenLengths: | ||
lst = seenLengths[length] | ||
if len(lst) > 1: | ||
for fileName in lst: | ||
filePath = os.path.join(path, fileName) | ||
# Destination path | ||
destination = os.path.join("./Duplicates/", fileName) | ||
shutil.copy(filePath, destination) | ||
random.shuffle(allVideos) | ||
|
||
duration = 0 | ||
# Add intro vid | ||
videos = [] | ||
if introName != '': | ||
introVid = VideoFileClip("./" + introName) | ||
videos.append(introVid) | ||
duration += introVid.duration | ||
|
||
description = "" | ||
# Create videos | ||
for clip in allVideos: | ||
timeRange = generateTimeRange(duration, clip.duration) | ||
acc = extractAcc(clip.filename) | ||
description += timeRange + " : @" + acc + "\n" | ||
duration += clip.duration | ||
videos.append(clip) | ||
print(duration) | ||
if duration >= totalVidLength: | ||
# Just make one video | ||
break | ||
|
||
# Add outro vid | ||
if outroName != '': | ||
outroVid = VideoFileClip("./" + outroName) | ||
videos.append(outroVid) | ||
|
||
finalClip = concatenate_videoclips(videos, method="compose") | ||
|
||
audio_path = "/tmp/temoaudiofile.m4a" | ||
|
||
#print(description) | ||
# Create compilation | ||
finalClip.write_videofile(outputFile, threads=8, temp_audiofile=audio_path, remove_temp=True, codec="libx264", audio_codec="aac") | ||
|
||
return description | ||
|
||
if __name__ == "__main__": | ||
makeCompilation(path = "/Users/nathanan/Documents/YOUTUBE/AutomatedChannel/Videos/Memes/", | ||
introName = "intro_vid.mp4", | ||
outroName = '', | ||
totalVidLength = 10*60, | ||
maxClipLength = 20, | ||
outputFile = "outputseq.mp4") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
google_api_python_client==1.12.8 | ||
google_auth_oauthlib==0.4.2 | ||
instaloader==4.5.5 | ||
instalooter==2.4.4 | ||
moviepy==1.0.3 | ||
protobuf==3.14.0 | ||
python_dateutil==2.8.1 | ||
schedule==0.6.0 |
Oops, something went wrong.