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,48 +17,106 @@ 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")
os.remove(f"{job_id}.mp4") f.write(":3")
os.remove(f"{job_id}.m4a") f.close()
os.remove(f"output.{job_id}.mp4") 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}.m4a")
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
letters = string.ascii_lowercase letters = string.ascii_lowercase
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("""
{ {
"success": true "success": true
} }
""") """)
@app.route("/get_merged_video") @app.route("/merge")
def get_merged_video(): def merge():
pwd = os.getcwd() job_id = get_random_string(10)
video_id = request.args.get("id") thread = Thread(target=merge_video, args = (job_id, request.args.get("id"), request.args.get("audio_itag"), request.args.get("video_itag")))
job_id = get_random_string(10) thread.start()
audio_itag = request.args.get("audio_itag") return json.loads('{"success":true,"job_id":"' + job_id + '"}')
video_itag = request.args.get("video_itag")
# Download both audio and video @app.route("/get")
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) def get():
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) pwd = os.getcwd()
# Merge both files job_id = request.args.get("job_id")
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) if os.path.isfile(f"{pwd}/done.{job_id}"):
thread = Thread(target=autodelete, args = (job_id, )) if not os.path.isfile(f"{pwd}/pendingDelete.{job_id}"):
thread.start() thread = Thread(target=autodelete, args = (job_id, ))
with open(f"output.{job_id}.mp4", "rb") as bytes: thread.start()
return send_file( with open(f"output.{job_id}.mp4", "rb") as bytes:
io.BytesIO(bytes.read()), return send_file(
mimetype="video/mp4", io.BytesIO(bytes.read()),
download_name=f"output.{job_id}.mp4", mimetype="video/mp4",
as_attachment=True download_name=f"output.{job_id}.mp4",
) 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
# )
#
#
#
#
#