mirror of
https://codeberg.org/ashley/poke.git
synced 2024-11-26 16:58:14 +01:00
Merge pull request 'improve videobundler' (#93) from nin0dev/poke:main into main
Reviewed-on: https://codeberg.org/ashley/poke/pulls/93
This commit is contained in:
commit
678e30c89a
3 changed files with 64 additions and 55 deletions
|
@ -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
|
|
@ -22,4 +22,5 @@ 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.
|
- `/[ANYTHING]?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.
|
||||||
|
> Replace `[ANYTHING]` with absolutely anything, however it has to be unique to the request. Preferably use an UUID
|
||||||
|
|
|
@ -1,26 +1,13 @@
|
||||||
from datetime import datetime
|
import asyncio
|
||||||
from dotenv import load_dotenv
|
import aiohttp
|
||||||
from flask import Flask, request, Response, send_file
|
from aiohttp import web
|
||||||
from threading import Thread
|
import string
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
import io
|
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import string
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import uuid
|
|
||||||
|
|
||||||
load_dotenv()
|
app = web.Application()
|
||||||
|
app.router._frozen = False
|
||||||
app = Flask(__name__)
|
|
||||||
|
|
||||||
def autodelete(job_id: str):
|
|
||||||
sleep(os.getenv("TIME_BEFORE_DELETE"))
|
|
||||||
os.remove(f"{job_id}.mp4")
|
|
||||||
os.remove(f"{job_id}.m4a")
|
|
||||||
os.remove(f"output.{job_id}.mp4")
|
|
||||||
|
|
||||||
def get_random_string(length):
|
def get_random_string(length):
|
||||||
# choose from all lowercase letter
|
# choose from all lowercase letter
|
||||||
|
@ -28,37 +15,57 @@ 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
|
||||||
|
|
||||||
@app.route("/")
|
async def merge(request):
|
||||||
def ping():
|
# register params
|
||||||
return json.loads("""
|
try:
|
||||||
{
|
job_id = request.rel_url.query["id"]
|
||||||
"success": true
|
video_id: str = request.rel_url.query["id"]
|
||||||
}
|
audio_itag: str = request.rel_url.query["audio_itag"]
|
||||||
""")
|
video_itag: str = request.rel_url.query["video_itag"]
|
||||||
|
except:
|
||||||
@app.route("/get_merged_video")
|
# no one gives a fuck
|
||||||
def get_merged_video():
|
_ = 0
|
||||||
pwd = os.getcwd()
|
# validate
|
||||||
video_id = request.args.get("id")
|
if " " in video_id or len(video_id) > 11:
|
||||||
job_id = get_random_string(10)
|
print(f"Video {video_id} flagged as invalid, dropping request")
|
||||||
audio_itag = request.args.get("audio_itag")
|
return
|
||||||
video_itag = request.args.get("video_itag")
|
if not audio_itag.isdigit():
|
||||||
# Download both audio and video
|
print(f"Audio itag {audio_itag} flagged as invalid, dropping request")
|
||||||
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)
|
return
|
||||||
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)
|
if not video_itag.isdigit():
|
||||||
# Merge both files
|
print(f"Video itag {video_itag} flagged as invalid, dropping request")
|
||||||
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)
|
return
|
||||||
thread = Thread(target=autodelete, args = (job_id, ))
|
if os.path.isfile(f"done.{job_id}"):
|
||||||
thread.start()
|
return web.FileResponse(
|
||||||
with open(f"output.{job_id}.mp4", "rb") as bytes:
|
path=f"output.{job_id}.mp4"
|
||||||
return send_file(
|
)
|
||||||
io.BytesIO(bytes.read()),
|
proc_audio = await asyncio.create_subprocess_shell(
|
||||||
mimetype="video/mp4",
|
f"wget -O{job_id}.m4a \"https://eu-proxy.poketube.fun/latest_version?id={video_id}&itag={audio_itag}&local=true\"",
|
||||||
download_name=f"output.{job_id}.mp4",
|
)
|
||||||
as_attachment=True
|
proc_video = await asyncio.create_subprocess_shell(
|
||||||
|
f"wget -O{job_id}.mp4 \"https://eu-proxy.poketube.fun/latest_version?id={video_id}&itag={video_itag}&local=true\""
|
||||||
|
)
|
||||||
|
await asyncio.gather(proc_audio.wait(), proc_video.wait())
|
||||||
|
proc_ffmpeg = await asyncio.create_subprocess_shell(
|
||||||
|
f"ffmpeg -i {job_id}.m4a -i {job_id}.mp4 -c copy output.{job_id}.mp4"
|
||||||
|
)
|
||||||
|
await proc_ffmpeg.wait()
|
||||||
|
f = open(f"done.{job_id}", "a")
|
||||||
|
f.write(":3")
|
||||||
|
f.close()
|
||||||
|
return web.FileResponse(
|
||||||
|
path=f"output.{job_id}.mp4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def ping(request):
|
||||||
|
return web.Response(body='{"success": true}', content_type="application/json")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
async def init_app():
|
||||||
from waitress import serve
|
app.router.add_get("/{id:.+}", merge)
|
||||||
serve(app, host="0.0.0.0", port=os.getenv("PORT"))
|
app.router.add_get("/", ping)
|
||||||
|
return app
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
app = loop.run_until_complete(init_app())
|
||||||
|
web.run_app(app, port=3030)
|
Loading…
Reference in a new issue