├── README.md ├── main.py ├── requirements.txt └── video_divider.py /README.md: -------------------------------------------------------------------------------- 1 | # TikTok-content-farm 2 | ![](https://www.iphones.ru/wp-content/uploads/2018/11/42C7C03E-1222-4B86-ADC7-987B085F15F8.png) 3 | Auto download all videos of some youtube channel and crop it into parts of 40 s to post them to the tick tok 4 | # NEW VERSION IS AVAILABLE NOW!! 5 | ## What is new 6 | * Now you should run just one program. It will upload and crop the video itself 7 | * Absolute path to video folder works correctly 8 | * Get channel id by it's name 9 | * Using faster lib to crop videos (x 150 - 200 %) boost 10 | ## Using 11 | * Clone this repo `git clone https://github.com/freQuensy23-coder/TikTok-content-farm` 12 | * Get youtube api key and paste it into field `youtube_api_key` in config file 13 | * Install libs (pip install -r requirements.txt) 14 | * Select channel in youtube with memes or other trash content. 15 | * Copy it's channel id to `channel_id` field. If you can't find channel id in link, use channel id finder (second tool) 16 | * Run main.py and follow the instructions 17 | * Videos will be downloaded to folder you selected. Cropped videos will be saved to ..._cropped folder 18 | ## Publishing to TikTok 19 | * Send downloaded videos to your phone (for ex. using Google Drive) 20 | * Create new TikTok account with login as the name of the YouTube channel. 21 | * Publish one video per 6-8 hours. 22 | * If the content of the channel that you have found is really trashy, you can quickly (in a month) promote your channel on tick tok and sell your account by going to a profit. 23 | ## Will be released in the next versions 24 | * Video preview and selection before downloading 25 | * Auto posting to Tik Tok using MIM proxy and unofficial API 26 | * Downloading by search query -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from pytube import YouTube 2 | import requests as req 3 | from tqdm import tqdm 4 | from config import * 5 | from pprint import pprint 6 | from pyyoutube import Api 7 | import logging 8 | import video_divider 9 | 10 | log = logging.getLogger("broadcast") 11 | 12 | 13 | def get_videos(channel_id: str)->list: 14 | """ 15 | :param channel_id - youtube channel id 16 | Get all videos of some chanel with id = channel_id 17 | """ 18 | r = req.get( 19 | f"https://www.googleapis.com/youtube/v3/search?key={youtube_api_key}&channel_id={channel_id}&orderby=published&part=snippet,id&order=date&maxResults=50") 20 | return r.json()["items"] 21 | 22 | 23 | def get_channel_id(channel_name: str) -> tuple: 24 | """:param channel_name - name of channel. You can find them in link, ex www.youtube.com/user/Google 25 | :returns Returns tuple. First is bool - True if we found only one channel with such name. 26 | """ 27 | channel_ids = api.get_channel_info(channel_name=channel_name) 28 | if len(channel_ids) == 0: 29 | raise Exception("No channel with such name") 30 | if len(channel_ids) == 1: 31 | return True, channel_ids[0] 32 | else: 33 | return False, channel_ids 34 | 35 | 36 | def download_channel_videos(channel_id, folder): 37 | videos = get_videos(channel_id) 38 | log.info(f"Get {len(videos)} videos") 39 | log.info("Start downloading ....") 40 | 41 | for video in tqdm(videos): 42 | if video["id"]["kind"] == "youtube#video": 43 | log.debug(f'Downloading video {video["id"]["videoId"]}') 44 | link = "https://www.youtube.com/watch?v=" + video["id"]["videoId"] 45 | yt = YouTube(link) 46 | yt.streams\ 47 | .filter(progressive=True, file_extension='mp4')\ 48 | .order_by('resolution')\ 49 | .desc()\ 50 | .first()\ 51 | .download(folder) 52 | log.debug(f'Downloaded video {video["id"]["videoId"]}') 53 | else: 54 | log.debug(f"{video} is not youtube#video") 55 | 56 | divide_videos = input("Do you want to divide downloaded videos into small parts (It is necessary if you want to " 57 | "download them to TikTok)? (Y/N)") 58 | if divide_videos == "Y": 59 | video_divider.divide_videos(folder_name=folder) 60 | 61 | return True 62 | 63 | 64 | if __name__ == '__main__': 65 | api = Api(api_key=youtube_api_key) 66 | log.debug("API inited") 67 | do = True 68 | while do: 69 | print("(0) Get last videos of some channel (by it's id)") 70 | print("(1) Get channel id by it's name") 71 | print("(2) Get last videos by some search query") 72 | action = input("What do you want to do \n") 73 | 74 | if action == "0": 75 | channel_id = input("Print channel id ") 76 | folder = input("Print folder_name ") 77 | download_channel_videos(channel_id, folder) 78 | log.info("Videos is downloaded") 79 | 80 | if action == "1": 81 | channel_name = input("Print channel name ") 82 | channel_id = get_channel_id(channel_name) 83 | log.info(f"Find {channel_name} id. It is {channel_id}.") 84 | download = input("Do you want to download it's last videos? (Y/N)") 85 | if download == "Y": 86 | folder = input("Print folder_name ") 87 | download_channel_videos(channel_id, folder) 88 | log.info("Videos is downloaded") 89 | 90 | if action == "2": 91 | print("Not supported") 92 | query = input("Print ") 93 | # TODO 94 | 95 | elif action == "c" or action == "q": 96 | do = False 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2020.12.5 2 | chardet==4.0.0 3 | colorama==0.4.4 4 | decorator==4.4.2 5 | ffmpeg==1.4 6 | idna==2.10 7 | imageio==2.9.0 8 | imageio-ffmpeg==0.4.2 9 | mo==0.3.0 10 | moviepy==1.0.3 11 | numpy==1.19.3 12 | Pillow==8.0.1 13 | proglog==0.1.9 14 | pytube==10.7.2 15 | pytube3==9.6.4 16 | PyYAML==5.3.1 17 | requests==2.25.1 18 | toml==0.10.2 19 | tqdm==4.54.1 20 | typing-extensions==3.7.4.3 21 | urllib3==1.26.2 22 | -------------------------------------------------------------------------------- /video_divider.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | from tqdm import tqdm 3 | from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip 4 | import os 5 | import time 6 | import moviepy.editor 7 | 8 | 9 | def get_length(path): 10 | video = moviepy.editor.VideoFileClip(path) 11 | return video.duration 12 | 13 | 14 | def get_result_folder_name(folder: str, filename: str, i:int)->str: 15 | """ 16 | :param folder: absolute path to folder with videos 17 | :param i: index of file in video 18 | :param filename: filename of input file 19 | :return: String - absolute path to folder to save results 20 | """ 21 | return folder + "_cropped\\" + filename + f"({str(i)})" + ".mp4" 22 | 23 | 24 | def divide_videos(folder_name, result_len: int = 40): 25 | """ 26 | :param folder_name: Relative path to folder with videos 27 | :param result_len: Duraction of extracted subclips in seconds. Default = 40 28 | :return: 29 | """ 30 | 31 | list_of_filenames = os.listdir(path=folder_name) 32 | 33 | for filename in tqdm(list_of_filenames): 34 | video_path = os.path.abspath(f"{folder_name}/{filename}") 35 | video_length = int(get_length(video_path)) 36 | os.mkdir(os.path.abspath(folder_name) + "_cropped") 37 | for second in tqdm(range(8, video_length - 8, result_len)): 38 | ffmpeg_extract_subclip(video_path, 39 | second, second + result_len, 40 | targetname=get_result_folder_name(os.path.abspath(folder_name), filename, second)) --------------------------------------------------------------------------------