Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@
# PyCharm
.idea/

build
dist

twitter_creds.json
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,19 @@
# PictureToBurn

A python package for gif-making.

## Setup and Installation
### Set up Twitter creds
* Generate access token. Full instructions at https://developer.twitter.com/en/docs/basics/authentication/guides/access-tokens
* Copy `twitter_creds.dist.json` to `twitter_creds.json`

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to put it in data/twitter_creds.json. Sound right?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* Add token details to `twitter_creds.json`

### Install
```
python setup.py install
```

## Running
```
create_gif [local_file | twitter_url]
```
32 changes: 24 additions & 8 deletions bin/create_gif
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,48 @@
import os
import warnings
from fire import Fire
import logging

from picture_to_burn import mp4_to_gif, find_mp4
from picture_to_burn import mp4_to_gif, find_video

log = logging.getLogger('create_gif')
log.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
log.addHandler(ch)

max_size = 2 #MB

def convert(some_mp4: str, width: int = 320):
"""
Convert something to a gif. Currently supports local .mp4 files and tweets.
"""
if os.path.isfile(some_mp4) or _is_ffmpegable_url(some_mp4):
log.info(f"Running with {some_mp4}")
if os.path.isfile(some_mp4):
pass
elif 'twitter.com' in some_mp4:
some_mp4 = find_mp4(some_mp4)
else:
log.info("Getting the video from Twitter")
some_mp4 = find_video(some_mp4, log)

if not _is_ffmpegable_url(some_mp4):
raise NotImplementedError(
f"Can't find a way to convert {some_mp4} into a gif")

gif = mp4_to_gif(some_mp4, width)

size_mb = os.path.getsize(gif) / 1000000
if size_mb > 2:
size_mb = _get_size(gif)
while size_mb > max_size:
log.info(f"Width {width}")
warnings.warn(f"Gif created is {size_mb:.02f} MB, "
f"and might not display in Slack. Making a smaller one.")
os.remove(gif)
gif = mp4_to_gif(some_mp4, width // 2)
width = width // 2
gif = mp4_to_gif(some_mp4, width)
size_mb = _get_size(gif)

print(f"Created gif: {gif}")
log.info(f"Created gif {gif} with size {size_mb} MB")

def _get_size(gif: str):
return os.path.getsize(gif) / 1000000

# At least, I've tried it with these
FFMPEGABLE = ['ts', 'mp4', 'm3u8']
Expand Down
2 changes: 1 addition & 1 deletion picture_to_burn/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .ffmpeg import mp4_to_gif
from .twitter import find_mp4
from .twitter_helper import find_video
20 changes: 0 additions & 20 deletions picture_to_burn/twitter.py

This file was deleted.

53 changes: 53 additions & 0 deletions picture_to_burn/twitter_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import twitter
import json
import sys
import os
from logging import Logger
import pkg_resources

def _get_creds():
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'data', 'twitter_creds.json'), 'r') as f:
creds = json.load(f)
return creds


def find_video(tweet_url: str, log: Logger) -> str:
r"""
Gets the video URL from the Tweet

:param tweet_url: URL for a tweet with a video.
:return: URL of the video itself.
"""
try:
creds = _get_creds()
api = twitter.Api(
consumer_key=creds['consumer_key'],
access_token_key=creds['access_token_key'],
consumer_secret=creds['consumer_secret'],
access_token_secret=creds['access_token_secret']
)
except Exception as e:
log.error(e)
raise Exception("There was a problem with your twitter creds")
tweet_id = tweet_url.strip("/").split("/")[-1]

status = api.GetStatus(tweet_id)
media = status.media

try:
video = media[0].AsDict()

saved_variant = None
# Default to m3u8, then highest quality mp4
for variant in video['video_info']['variants']:
if variant['content_type'] == 'application/x-mpegURL':
saved_variant = variant
break
elif saved_variant == None:
saved_variant = variant
elif variant['content_type'] == "video/mp4" and variant['bitrate'] > saved_variant['bitrate']:
saved_variant = variant

return saved_variant['url'].split("?")[0] #Remove query string
except Exception as e:
raise Exception("There's no video on this Twitter post")
4 changes: 1 addition & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
cssselect==1.0.3
docopt==0.6.2
fire==0.1.3
lxml==4.1.1
requests==2.21.0
python-twitter==3.5
5 changes: 2 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
name='picture-to-burn',
packages=find_packages(),
install_requires=[
'cssselect',
'python-twitter',
'docopt',
'lxml',
'requests',
],
scripts=['bin/create_gif'],
data_files=[('data', ['twitter_creds.json'])],
version='0.0.1',
)
6 changes: 6 additions & 0 deletions twitter_creds.dist.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"consumer_key": "xxxxx",
"access_token_key": "xxxxx",
"consumer_secret": "xxxxx",
"access_token_secret": "xxxxx"
}