Skip to content

Commit

Permalink
Merge pull request #9 from andrew-hossack/dev
Browse files Browse the repository at this point in the history
Version 0.0.2
  • Loading branch information
andrew-hossack committed Mar 9, 2021
2 parents bb30519 + 7f94645 commit 1dfce22
Show file tree
Hide file tree
Showing 18 changed files with 326 additions and 113 deletions.
7 changes: 1 addition & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,2 @@
__pycache__
lib/AutoCompiler/private
lib/AutoCompiler/temp
lib/AutoCompiler/output
lib/AutoCompiler/private.py
dat/*
__init__.pyc
*.pyc
4 changes: 4 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include vidtools/video.yaml
include vidtools/examples
include vidtools/lib/refreshtokengen.py
graft vidtools/dat
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# YouTube Automation Project
# VidTools Content Creation Library
A project for automating the simple task of uploading mindless content to YouTube. This library is written to leverage different input video sources and includes resources like TikTokTools to get content.

In the future, other sources of video, audio, and text-based content will be provided such as Reddit over Text To Speech (TTS) and more.

## Installation Instructions
To install this package using pip, in the root directory *vidtools/* run the command
```bash
pip install .
```

## ```TikTokTools Class```
Built on [TikTokApi by David Teather](https://github.com/davidteather/TikTok-Api), ```TikTokTools``` is a wrapper class to enable the user to quickly source content from TikTok without needing developer API access.

Expand Down Expand Up @@ -54,6 +60,17 @@ print(videoInstance.author)
videotools.video_downloader_from_url(downloadaddr)
```

Another helpful method is ```update_config(updated_dict)```. This method can be used to safely update ```video.yaml``` file.

```python
updated_dict = {
'video': {
'title':'123455'
}
}
vt.update_config(updated_dict)
```

## ```YouTubeTools Class```
A wrapper class for ```googleapiclient``` [https://developers.google.com/youtube/v3/guides/uploading_a_video](https://developers.google.com/youtube/v3/guides/uploading_a_video
), this class adds functionality to upload videos to YouTube.
Expand All @@ -76,7 +93,7 @@ Please see ```__init__``` for more details.
### Examples

```python
instance = YouTubeTools()
instance = YouTubeTools(file='video.mp4')
youtube = instance.get_authenticated_service()

# Try to upload a file out.mp4 located in /dat
Expand Down Expand Up @@ -105,4 +122,21 @@ author = rt.get_author()
text = rt.get_selftext()

print(f'{title} by {author}\n{text}')
```

## ```TTSTools Class```
Text To Speech (TTS) Tools ```TTSTools``` class is a helper class and wrapper for using Google wavenet Text To Speech. More information about the google tts client libraries can be found at the link [https://cloud.google.com/docs/authentication/production](https://cloud.google.com/docs/authentication/production).

The main functionality of this class is to synthesize lifelike voice from a text entry.

### Examples

```python
# Instantiate TTSHelper and save outfile to dat/audio.mp3
tts = TTSHelper(outfile_name='audio.mp3')

# Load in text file
with open('dat/exampletextfile.txt') as file:
# Synthesize speech
tts.synthesize_text(file)
```
31 changes: 0 additions & 31 deletions UploadTikTok.py

This file was deleted.

9 changes: 8 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
with open("README.md", "r", encoding="utf-8") as fh:
long_description = fh.read()

# TODO Figure out how to include /examples, /lib, /dat
# vidtools/private in the install

setuptools.setup(
name="VidTools",
version="0.0.2",
version="0.0.3",
author="Andrew Hossack",
author_email="[email protected]",
description="VidTools is a video tools python package",
Expand All @@ -22,10 +25,14 @@
],
packages=setuptools.find_packages(),
python_requires=">=3.6",
include_package_data=True,
install_requires=[
"google-api-python-client",
"TikTokApi",
"oauth2client",
"praw",
"google-cloud",
"google-cloud-core",
"google-cloud-texttospeech"
]
)
16 changes: 0 additions & 16 deletions video.yaml

This file was deleted.

18 changes: 11 additions & 7 deletions vidtools/RedditTools.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,23 @@
from praw.models import MoreComments
import sys

class RedditTools():
class RedditTools:
'''
Wrapper class for praw
https://praw.readthedocs.io/en/latest/
'''
def __init__(self):
def __init__(self, secrets_filepath):
'''
self.prawclient (praw): PRAW Client instance
self.submission (post): PRAW post object, must call
set_url(url) to use other methods
args:
secrets_filepath (str):
Absolute path to secrets file
callables:
self.prawclient (praw): PRAW Client instance
self.submission (post): PRAW post object, must call
set_url(url) to use other methods
'''
self._secrets_dir = Path(
f'{Path(os.path.join(os.path.dirname(__file__)))}/private/reddit_client_secrets.json')
self._secrets_dir = Path(secrets_filepath)
with open(self._secrets_dir) as redditsecrets:
self._secrets = json.load(redditsecrets)
self.prawclient = praw.Reddit(client_id=self._secrets['web']['client_id'],
Expand Down
63 changes: 63 additions & 0 deletions vidtools/TTSTools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
'''
# @ Author: Andrew Hossack
# @ Create Time: 2021-03-07 18:31:20
# @ Description: Text To Speech class
'''

from google.cloud import texttospeech
import os
from pathlib import Path

class TTSHelper:
'''
Text to speech helper class
https://googleapis.dev/python/texttospeech/latest/index.html
'''
def __init__(self, secrets_filepath, outfile_name='audio.mp3', **kwargs):
'''
args:
secrets_filepath (str):
Absolute path to secrets file json
kwargs:
outfile_name (str): name of audio output file
Defaults to audio.mp3
'''
self._text = None
self._output_directory = Path(os.path.join(os.path.dirname(__file__))).joinpath('dat')
self._secrets_filepath = Path(secrets_filepath)
self._outfile_name = outfile_name
self._client = texttospeech.TextToSpeechClient()
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = self._secrets_filepath

def synthesize_speech(self, text, language_code="en-US", ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL):
"""Synthesizes speech from the input string of text or ssml.
Note: ssml must be well-formed according to:
https://www.w3.org/TR/speech-synthesis/
"""
self._text = text

# Set the text input to be synthesized
synthesis_input = texttospeech.SynthesisInput(text=self._text)

# Build the voice request, select the language code ("en-US") and the ssml
# voice gender ("neutral")
voice = texttospeech.VoiceSelectionParams(
language_code=language_code, ssml_gender=ssml_gender
)

# Select the type of audio file you want returned
audio_config = texttospeech.AudioConfig(
audio_encoding=texttospeech.AudioEncoding.MP3
)

# Perform the text-to-speech request on the text input with the selected
# voice parameters and audio file type
response = self._client.synthesize_speech(
input=synthesis_input, voice=voice, audio_config=audio_config
)

# The response's audio_content is binary.
with open(f'{self._output_directory}/{self._outfile_name}', "wb") as out:
# Write the response to the output file.
out.write(response.audio_content)
print('Audio content written to file "output.mp3"')
51 changes: 39 additions & 12 deletions vidtools/TikTokTools.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from TikTokApi import TikTokApi
from queue import Queue

class TikTokTools():
class TikTokTools:
'''
TikTok Tools wrapper for TikTokApi
https://github.com/davidteather/TikTok-Api
Expand All @@ -18,18 +18,18 @@ def __init__(self, verbosity=0, **kwargs):
1 = print statements
2 = extra verbose
'''
self.api = TikTokApi(**kwargs)
self._api = TikTokApi(**kwargs)
self._videos = Queue() # Implemented Queue for fun
self.requested_length = 0
self._requested_length = 0
self._verbosity = verbosity

def _check_video_shorter_than(self, video_entry):
'''
Returns boolean if video is less than given length
'''
res = video_entry['video']['duration'] < self.requested_length
res = video_entry['video']['duration'] < self._requested_length
if self._verbosity:
print(f"Video shorter than {self.requested_length}: {res}")
print(f"Video shorter than {self._requested_length}: {res}")
return res

def _check_video_not_in_list(self, video):
Expand All @@ -51,20 +51,30 @@ def _check_video_not_in_list(self, video):
print(f'not_in_list {not_in_list}')
return not_in_list

def get_video_list(self, num_videos_requested, length_seconds, buffer_len=30):
def get_video_list(self, num_videos_requested, max_length_seconds, buffer_len=30):
'''
buffer_length (int): number of unparsed videos to initially download
Return video list
videos (list): list of dictionary tiktok objects
args:
num_videos_requested (int):
Number of videos to try to return based on length parameter
max_length_seconds (int):
Filter video list by maximum length. Will try to return a list
of videos no longer than length_seconds
kwargs:
buffer_length (int):
number of unparsed videos to initially download
This is a hotfix to solve getting unique tiktoks
Returns:
videos (list):
list of dictionary tiktok objects
'''
# TODO BUG every time a new video is requested, it always retrieves
# the first video in a list somewhere that is always the same. Need
videolist_raw = self.api.trending(buffer_len, custom_verifyFp="")
videolist_raw = self._api.trending(buffer_len, custom_verifyFp="")
# to retrieve unique video.
# HOTFIX: Retrieve a list of 20, 30, 50 videos and parse through each
# of those as the results.
self.requested_length = length_seconds
self._requested_length = max_length_seconds
for video in videolist_raw:
# TODO eventually implement where new UNIQUE video is retrieved until list
# is full
Expand Down Expand Up @@ -94,6 +104,23 @@ def _get_video_by_keyword(self):
'''
raise NotImplementedError

def get_video_author(self, tiktokobject):
'''
Get video author
'''
return tiktokobject['desc']

def get_video_download_address(self, tiktokobject):
'''
Get video download address
'''
return tiktokobject['video']['downloadAddr']

def get_video_description(self, tiktokobject):
'''
Get video description
'''
return tiktokobject['author']['nickname']

'''
~~~~~~~~~~~~~~~~~~~ TODO List ~~~~~~~~~~~~~~~~~~~
Expand Down
Loading

0 comments on commit 1dfce22

Please sign in to comment.