Added concurrency

This commit is contained in:
nin0dev 2024-06-22 18:02:30 -04:00
parent a1e1c3e33f
commit bbff542938
3 changed files with 98 additions and 37 deletions

View file

@ -1,4 +1,5 @@
TIME_BEFORE_DELETE=30 TIME_BEFORE_DELETE=30
INACTIVE_TIME_BEFORE_DELETE=3600
PORT=45872 PORT=45872
# DO NOT PUT A / AT THE END OF THE URL # DO NOT PUT A / AT THE END OF THE URL
PROXY_URL=https://eu-proxy.poketube.fun PROXY_URL=https://eu-proxy.poketube.fun

View file

@ -22,4 +22,6 @@ Takes 2 input streams, downloads them, and spits out a combined file.
## Endpoints ## Endpoints
- `/`: Will return `{success:true}` if alive. - `/`: Will return `{success:true}` if alive.
- `/get_merged_video?id=VIDEO_ID&audio_itag=AUDIO_ITAG&video_itag=VIDEO_ITAG`: Returns a merged video. ID is the youtube video ID, and itags are self explanatory. - `/merge?id=VIDEO_ID&audio_itag=AUDIO_ITAG&video_itag=VIDEO_ITAG`: Starts the merging process. ID is the youtube video ID, and itags are self explanatory. As a response, you will get a job ID that you will be able to use in future requests to query the video or its status. When this process is finished, the inactive autodelete counter will start, which will allow you to fetch the video until the countdown is over.
- `/get?id=JOB_ID`: Queries a merged video and sends it to you. If the video is successfully and fully merged you will get a 200 response with a video. However, if it isn't finished, you will get a `success: false` 404 response. If the video indeed exists and is sent to you, the get autodelete counter will start, which will allow you to fetch it until this countdown is over.
- `/check?id=JOB_ID`: Queries a merged video's status. If the video is successfully and fully merged you will get a 200 response with `success:true`. However, if it isn't finished, you will get a `success: false` 404 response. Useful if you want to poll the status without triggering the get autodelete counter.

View file

@ -17,10 +17,32 @@ load_dotenv()
app = Flask(__name__) app = Flask(__name__)
def autodelete(job_id: str): def autodelete(job_id: str):
sleep(os.getenv("TIME_BEFORE_DELETE")) f = open(f"pendingDelete.{job_id}", "a")
f.write(":3")
f.close()
sleep(int(os.getenv("TIME_BEFORE_DELETE")))
try:
os.remove(f"done.{job_id}")
os.remove(f"{job_id}.mp4") os.remove(f"{job_id}.mp4")
os.remove(f"{job_id}.m4a") os.remove(f"{job_id}.m4a")
os.remove(f"output.{job_id}.mp4") os.remove(f"output.{job_id}.mp4")
os.remove(f"pendingDelete.{job_id}")
except Exception:
_ = 0
def inactive_autodelete(job_id: str):
pwd = os.getcwd()
sleep(int(os.getenv("INACTIVE_TIME_BEFORE_DELETE")))
if not os.path.isfile(f"{pwd}/done.{job_id}"):
return
try:
os.remove(f"done.{job_id}")
os.remove(f"{job_id}.mp4")
os.remove(f"{job_id}.m4a")
os.remove(f"output.{job_id}.mp4")
os.remove(f"pendingDelete.{job_id}")
except Exception:
_ = 0
def get_random_string(length): def get_random_string(length):
# choose from all lowercase letter # choose from all lowercase letter
@ -28,6 +50,19 @@ def get_random_string(length):
result_str = "".join(random.choice(letters) for i in range(length)) result_str = "".join(random.choice(letters) for i in range(length))
return result_str return result_str
def merge_video(job_id: str, video_id: str, audio_itag: str, video_itag: str):
pwd = os.getcwd()
# Download both audio and video
subprocess.run(["wget", f"-O{job_id}.m4a", f"{os.getenv("PROXY_URL")}/latest_version?id={video_id}&itag={audio_itag}&local=true"], check=True)
subprocess.run(["wget", f"-O{job_id}.mp4", f"{os.getenv("PROXY_URL")}/latest_version?id={video_id}&itag={video_itag}&local=true"], check=True)
# Merge both files
subprocess.run(f"ffmpeg -i {pwd}/{job_id}.m4a -i {pwd}/{job_id}.mp4 -c copy {pwd}/output.{job_id}.mp4", shell=True, check=True)
f = open(f"done.{job_id}", "a")
f.write(":3")
f.close()
thread = Thread(target=inactive_autodelete, args = (job_id, ))
thread.start()
@app.route("/") @app.route("/")
def ping(): def ping():
return json.loads(""" return json.loads("""
@ -36,18 +71,19 @@ def ping():
} }
""") """)
@app.route("/get_merged_video") @app.route("/merge")
def get_merged_video(): def merge():
pwd = os.getcwd()
video_id = request.args.get("id")
job_id = get_random_string(10) job_id = get_random_string(10)
audio_itag = request.args.get("audio_itag") thread = Thread(target=merge_video, args = (job_id, request.args.get("id"), request.args.get("audio_itag"), request.args.get("video_itag")))
video_itag = request.args.get("video_itag") thread.start()
# Download both audio and video return json.loads('{"success":true,"job_id":"' + job_id + '"}')
subprocess.run(["wget", f"-O{job_id}.m4a", f"{os.getenv('PROXY_URL')}/latest_version?id={video_id}&itag={audio_itag}&local=true"], check=True)
subprocess.run(["wget", f"-O{job_id}.mp4", f"{os.getenv('PROXY_URL')}/latest_version?id={video_id}&itag={video_itag}&local=true"], check=True) @app.route("/get")
# Merge both files def get():
subprocess.run(f"ffmpeg -i {pwd}/{job_id}.m4a -i {pwd}/{job_id}.mp4 -c copy {pwd}/output.{job_id}.mp4", shell=True, check=True) pwd = os.getcwd()
job_id = request.args.get("job_id")
if os.path.isfile(f"{pwd}/done.{job_id}"):
if not os.path.isfile(f"{pwd}/pendingDelete.{job_id}"):
thread = Thread(target=autodelete, args = (job_id, )) thread = Thread(target=autodelete, args = (job_id, ))
thread.start() thread.start()
with open(f"output.{job_id}.mp4", "rb") as bytes: with open(f"output.{job_id}.mp4", "rb") as bytes:
@ -57,8 +93,30 @@ def get_merged_video():
download_name=f"output.{job_id}.mp4", download_name=f"output.{job_id}.mp4",
as_attachment=True as_attachment=True
) )
return json.loads('{"success":false}'), 404
@app.route("/check")
def check():
pwd = os.getcwd()
job_id = request.args.get("job_id")
if os.path.isfile(f"{pwd}/done.{job_id}"):
return json.loads('{"success":true}')
return json.loads('{"success":false}'), 404
if __name__ == "__main__": if __name__ == "__main__":
from waitress import serve from waitress import serve
serve(app, host="0.0.0.0", port=os.getenv("PORT")) serve(app, host="0.0.0.0", port=os.getenv("PORT"))
#with open(f"output.{job_id}.mp4", "rb") as bytes:
#return send_file(
# io.BytesIO(bytes.read()),
# mimetype="video/mp4",
# download_name=f"output.{job_id}.mp4",
# as_attachment=True
# )
#
#
#
#
#