· 4 years ago · Apr 30, 2021, 09:18 AM
1#!/usr/bin/env python
2
3import re
4import math
5import argparse
6import subprocess
7import tempfile
8import os
9import sys
10import requests
11#import pyperclip
12#import atexit
13
14def getArgs():
15 """ Get command-line arguments
16 """
17 parser = argparse.ArgumentParser()
18 parser.add_argument('input', action='store', type=str,
19 help='Input file')
20 parser.add_argument('-k', dest='key', action='store', type=str, required=True,
21 help='HDB Passkey')
22 parser.add_argument('-u', dest='username', action='store', type=str, required=True,
23 help='HDB Username')
24 parser.add_argument('-i', dest='interval', action='store', type=int, default=600,
25 help='Take screenshot between each <INTERVAL> seconds of the video (default: 600)')
26 parser.add_argument('-n', dest='num', action='store', type=int, default=8,
27 help='Number of screenshots to upload (default: 8)')
28# parser.add_argument('-c', dest='copy', action='store_true',
29# help='Copy BBCode to clipboard')
30 return parser.parse_args()
31
32def absoluteFilePaths(directory):
33 """ Get full file paths within a specific directory
34
35 Keyword arguments:
36 directory -- directory path containing files
37 """
38 files = []
39 for dirpath,_,filenames in os.walk(directory):
40 for f in sorted(filenames):
41 files.append(os.path.abspath(os.path.join(dirpath, f)))
42 return files
43
44def readFiles(files, key = 'images_files[]'):
45 """ Open files for Requests payload
46
47 Keyword arguments:
48 files -- list of files (full paths)
49 key -- Requests payload form field name
50 """
51 result = []
52 for f in files:
53 result.append((key, (os.path.basename(f), open(f, 'rb'))))
54 return result
55
56def largestFiles(files, limit = 8):
57 """ Trims the files list to the specified limit, discarding the smallest files from the list
58 Thanks to LeFirstTimer for the suggestion and sample code!
59
60 Keyword arguments:
61 files -- list of files (full paths)
62 limit -- Maximum number of files
63 """
64 if len(files) <= limit:
65 return files
66 pairs=[]
67 for file in files:
68 size = os.path.getsize(file)
69 pairs.append((file,size))
70 pairs.sort(key = lambda s: s[1], reverse=True)
71 pairs = pairs[:limit]
72 pairs.sort(key = lambda s: s[0])
73 return [x[0] for x in pairs]
74
75def getDuration(file):
76 """ Get duration of video file (in seconds)
77
78 Keyword arguments:
79 file -- input file (full path)
80 """
81 p = subprocess.Popen([
82 'ffprobe',
83 '-v', 'error',
84 '-show_entries', 'format=duration',
85 '-of', 'default=noprint_wrappers=1:nokey=1',
86 file
87 ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
88 duration = p.stdout.read().decode('utf-8')
89 retval = p.wait()
90 if retval == 127:
91 raise ValueError('ffprobe is not installed.')
92 return int(math.floor(float(duration)))
93
94def mkScreenshot(file, outputDir, offset):
95 """ Make a screenshot from file in specified output dir, with the specified offset
96
97 Keyword arguments:
98 file -- input file (full path)
99 outputDir -- directory to write screenshot to
100 offset -- how many seconds into the file to pull the screenshot from
101 """
102 p = subprocess.Popen([
103 'ffmpeg',
104 '-ss', str(offset),
105 '-r', '1',
106 '-i', file,
107 outputDir + '/ss' + str(offset).zfill(5) + '.png'
108 ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
109 retval = p.communicate()
110# if retval == 127:
111# raise ValueError('ffmpeg is not installed.')
112 return True
113
114def mkScreenshots(file, count, interval = 600):
115 """ Make screenshots from file, with the specified interval between screenshots
116
117 Keyword arguments:
118 file -- input file (full path)
119 interval -- interval between screenshots (seconds)
120 """
121 os.mkdir(args.input[:-4])
122 tempdir = args.input[:-4]
123# atexit.register(removeDir, tempdir)
124
125 for i in range(1, count + 1):
126 sys.stdout.write(str(i) + '.. ')
127 sys.stdout.flush()
128 mkScreenshot(file, tempdir, i * interval)
129 print('Done!')
130 return absoluteFilePaths(tempdir)
131
132def uploadScreenshots(user, key, title, files):
133 """ Upload screenshots to AIMG
134
135 Keyword arguments:
136 key -- AIMG API key
137 title -- Gallery title
138 files - list of images (full paths)
139 """
140 payload = {
141 'username': user,
142 'passkey': key,
143 'galleryname': title
144 }
145 s = requests.Session()
146 req = requests.Request(
147 'POST',
148 'https://img.hdbits.org/upload_api.php',
149 data=payload,
150 files=readFiles(files)
151 )
152 prepped = req.prepare()
153 resp = s.send(prepped)
154 if resp.status_code != 200:
155 raise ValueError('Error code from HDB: ' + str(resp.status_code))
156 return resp.text
157
158def removeDir(directory):
159 """ Removes a directory including all files in that directory
160
161 Keyword arguments:
162 directory -- directory path containing files
163 """
164 files = absoluteFilePaths(directory)
165 for f in files:
166 os.remove(f)
167 os.rmdir(directory)
168
169
170#-----------------------------------------------------------------------------
171# Begin the main program.
172#-----------------------------------------------------------------------------
173
174# Get command-line arguments
175args = getArgs()
176
177# Get duration of input file
178duration = getDuration(args.input)
179if math.floor(duration / args.interval) == 0:
180 raise ValueError('The input file (' + str(duration) + ' seconds) must be longer than the ' \
181 'interval (' + str(args.interval) + ' seconds).')
182
183# Count number of screenshots to generate
184count = int(math.floor(duration / args.interval))
185
186print('Input file is ' + str(duration) + ' seconds long. ' \
187 'This will generate ' + str(count) + ' screenshots.')
188
189# Generate screenshots
190print('Generating screenshots...')
191screenshots = mkScreenshots(args.input, count, args.interval)
192if len(screenshots) == 0:
193 raise ValueError('No screenshots generated. Quitting!')
194print(str(len(screenshots)) + ' screenshots generated.')
195
196# Get the largest screenshots limited to args.num
197if args.num:
198 screenshots = largestFiles(screenshots, args.num)
199
200# Upload screenshots
201print('Uploading ' + str(len(screenshots)) + ' screenshots...');
202uploads = uploadScreenshots(args.username, args.key, os.path.basename(args.input), screenshots)
203
204# Check result for successful uploads
205bbcode = str()
206bbcode = uploads
207
208# Output results
209print("BBCode:\n")
210print(bbcode)
211
212# Copy BBcode to clipboard
213#if args.copy:
214# print('Copying BBCode to Clipboard...')
215# pyperclip.copy(bbcode)
216
217# Cleanup
218print('Done!')
219