CAM4Recorder/CAM4Recorder.py

137 lines
5.6 KiB
Python
Raw Normal View History

import requests, time, datetime, os, threading, sys, configparser
2017-05-30 07:12:24 +08:00
from livestreamer import Livestreamer
if os.name == 'nt':
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
from subprocess import call
from queue import Queue
2017-05-30 07:12:24 +08:00
mainDir = sys.path[0]
Config = configparser.ConfigParser()
setting = {}
def readConfig():
global setting
global filter
Config.read(mainDir + "/config.conf")
setting = {
'save_directory': Config.get('paths', 'save_directory'),
'wishlist': Config.get('paths', 'wishlist'),
'interval': int(Config.get('settings', 'checkInterval')),
'postProcessingCommand': Config.get('settings', 'postProcessingCommand'),
}
try:
setting['postProcessingThreads'] = int(Config.get('settings', 'postProcessingThreads'))
except ValueError:
if setting['postProcessingCommand'] and not setting['postProcessingThreads']:
setting['postProcessingThreads'] = 1
if not os.path.exists("{path}".format(path=setting['save_directory'])):
os.makedirs("{path}".format(path=setting['save_directory']))
2017-05-30 07:12:24 +08:00
recording = []
UserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Mobile Safari/537.36"
offline = False
2017-07-21 05:17:13 +08:00
def getOnlineModels(page):
i = 1
while i < 5:
2017-05-30 08:31:47 +08:00
try:
sys.stdout.write("\033[K")
print("{} model(s) are being recorded. Checking for models to record (page {})".format(len(recording), page))
sys.stdout.write("\033[K")
print("the following models are being recorded: {}".format(recording), end="\r")
result = requests.get("https://www.cam4.com/directoryCams?directoryJson=true&online=true&url=true&page={}".format(page)).json()
return result
2017-05-30 08:31:47 +08:00
except:
i = i + 1
2017-05-30 08:37:30 +08:00
sys.stdout.write("\033[F")
2017-05-30 07:12:24 +08:00
def startRecording(model):
2017-05-30 12:26:18 +08:00
try:
2017-07-21 05:17:13 +08:00
model = model.lower()
resp = requests.get('https://www.cam4.com/' + model, headers={'user-agent':'UserAgent'}).text.splitlines()
2017-05-30 12:26:18 +08:00
videoPlayUrl = ""
videoAppUrl = ""
for line in resp:
if "videoPlayUrl" in line:
for part in line.split("&"):
if "videoPlayUrl" in part and videoPlayUrl == "":
videoPlayUrl = part[13:]
elif "videoAppUrl" in part and videoAppUrl == "":
videoAppUrl = part.split("//")[1]
session = Livestreamer()
session.set_option('http-headers', "referer=https://www.cam4.com/{}".format(model))
2017-07-21 05:17:13 +08:00
streams = session.streams("hlsvariant://https://{}/amlst:{}_aac/playlist.m3u8?referer=www.cam4.com&timestamp={}"
2017-05-30 12:26:18 +08:00
.format(videoAppUrl, videoPlayUrl, str(int(time.time() * 1000))))
stream = streams["best"]
fd = stream.open()
ts = time.time()
st = datetime.datetime.fromtimestamp(ts).strftime("%Y.%m.%d_%H.%M.%S")
file = os.path.join(setting['save_directory'], model, "{st}_{model}.mp4".format(path=setting['save_directory'], model=model,
st=st))
os.makedirs(os.path.join(setting['save_directory'], model), exist_ok=True)
with open(file, 'wb') as f:
2017-07-21 05:17:13 +08:00
recording.append(model)
2017-05-30 12:26:18 +08:00
while True:
try:
data = fd.read(1024)
f.write(data)
except:
break
if setting['postProcessingCommand']:
processingQueue.put({'model': model, 'path': file})
finally:
2017-05-30 21:20:58 +08:00
if model in recording:
recording.remove(model)
2017-05-30 07:12:24 +08:00
def postProcess():
while True:
while processingQueue.empty():
time.sleep(1)
parameters = processingQueue.get()
model = parameters['model']
path = parameters['path']
filename = os.path.split(path)[-1]
directory = os.path.dirname(path)
file = os.path.splitext(filename)[0]
call(setting['postProcessingCommand'].split() + [path, filename, directory, model, file, 'cam4'])
2017-05-30 07:12:24 +08:00
if __name__ == '__main__':
readConfig()
if setting['postProcessingCommand']:
processingQueue = Queue()
postprocessingWorkers = []
for i in range(0, setting['postProcessingThreads']):
t = threading.Thread(target=postProcess)
postprocessingWorkers.append(t)
t.start()
2017-05-30 07:12:24 +08:00
while True:
readConfig()
2017-05-30 07:12:24 +08:00
wanted = []
i = 1
with open(setting['wishlist']) as f:
2017-05-30 07:12:24 +08:00
for model in f:
models = model.split()
for theModel in models:
wanted.append(theModel.lower())
2017-09-24 02:10:01 +08:00
online = []
2017-05-30 07:12:24 +08:00
while not offline:
results = getOnlineModels(i)
if len(results['users']) >= 1:
2017-09-24 02:10:01 +08:00
online.extend([user['username'].lower() for user in results['users']])
2017-05-30 07:12:24 +08:00
else:
offline = True
i = i + 1
sys.stdout.write("\033[F")
offline = False
2017-09-24 02:10:01 +08:00
for model in list(set(set(online) - set(recording)).intersection(set(wanted))):
thread = threading.Thread(target=startRecording, args=(model.lower(),))
thread.start()
for i in range(setting['interval'], 0, -1):
2017-05-30 07:12:24 +08:00
sys.stdout.write("\033[K")
print("{} model(s) are being recorded. Next check in {} seconds".format(len(recording), i))
sys.stdout.write("\033[K")
print("the following models are being recorded: {}".format(recording), end="\r")
time.sleep(1)
sys.stdout.write("\033[F")