mirror of
https://codeberg.org/ashley/poke.git
synced 2024-12-26 05:08:39 +01:00
removed videobundler
This commit is contained in:
parent
0f26c1904b
commit
def048716a
4 changed files with 0 additions and 300 deletions
|
@ -1,5 +0,0 @@
|
||||||
TIME_BEFORE_DELETE=30
|
|
||||||
INACTIVE_TIME_BEFORE_DELETE=3600
|
|
||||||
PORT=45872
|
|
||||||
# DO NOT PUT A / AT THE END OF THE URL
|
|
||||||
PROXY_URL=https://eu-proxy.poketube.fun
|
|
170
videobundler/.gitignore
vendored
170
videobundler/.gitignore
vendored
|
@ -1,170 +0,0 @@
|
||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
__pycache__/
|
|
||||||
*.py[cod]
|
|
||||||
*$py.class
|
|
||||||
|
|
||||||
# C extensions
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Distribution / packaging
|
|
||||||
.Python
|
|
||||||
build/
|
|
||||||
develop-eggs/
|
|
||||||
dist/
|
|
||||||
downloads/
|
|
||||||
eggs/
|
|
||||||
.eggs/
|
|
||||||
lib/
|
|
||||||
lib64/
|
|
||||||
parts/
|
|
||||||
sdist/
|
|
||||||
var/
|
|
||||||
wheels/
|
|
||||||
share/python-wheels/
|
|
||||||
*.egg-info/
|
|
||||||
.installed.cfg
|
|
||||||
*.egg
|
|
||||||
MANIFEST
|
|
||||||
|
|
||||||
# PyInstaller
|
|
||||||
# Usually these files are written by a python script from a template
|
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
||||||
*.manifest
|
|
||||||
*.spec
|
|
||||||
|
|
||||||
# Installer logs
|
|
||||||
pip-log.txt
|
|
||||||
pip-delete-this-directory.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
|
||||||
htmlcov/
|
|
||||||
.tox/
|
|
||||||
.nox/
|
|
||||||
.coverage
|
|
||||||
.coverage.*
|
|
||||||
.cache
|
|
||||||
nosetests.xml
|
|
||||||
coverage.xml
|
|
||||||
*.cover
|
|
||||||
*.py,cover
|
|
||||||
.hypothesis/
|
|
||||||
.pytest_cache/
|
|
||||||
cover/
|
|
||||||
|
|
||||||
# Translations
|
|
||||||
*.mo
|
|
||||||
*.pot
|
|
||||||
|
|
||||||
# Django stuff:
|
|
||||||
*.log
|
|
||||||
local_settings.py
|
|
||||||
db.sqlite3
|
|
||||||
db.sqlite3-journal
|
|
||||||
|
|
||||||
# Flask stuff:
|
|
||||||
instance/
|
|
||||||
.webassets-cache
|
|
||||||
|
|
||||||
# Scrapy stuff:
|
|
||||||
.scrapy
|
|
||||||
|
|
||||||
# Sphinx documentation
|
|
||||||
docs/_build/
|
|
||||||
|
|
||||||
# PyBuilder
|
|
||||||
.pybuilder/
|
|
||||||
target/
|
|
||||||
|
|
||||||
# Jupyter Notebook
|
|
||||||
.ipynb_checkpoints
|
|
||||||
|
|
||||||
# IPython
|
|
||||||
profile_default/
|
|
||||||
ipython_config.py
|
|
||||||
|
|
||||||
# pyenv
|
|
||||||
# For a library or package, you might want to ignore these files since the code is
|
|
||||||
# intended to run in multiple environments; otherwise, check them in:
|
|
||||||
# .python-version
|
|
||||||
|
|
||||||
# pipenv
|
|
||||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
||||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
||||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
||||||
# install all needed dependencies.
|
|
||||||
#Pipfile.lock
|
|
||||||
|
|
||||||
# poetry
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
||||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
||||||
# commonly ignored for libraries.
|
|
||||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
||||||
#poetry.lock
|
|
||||||
|
|
||||||
# pdm
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
||||||
#pdm.lock
|
|
||||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
||||||
# in version control.
|
|
||||||
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
||||||
.pdm.toml
|
|
||||||
.pdm-python
|
|
||||||
.pdm-build/
|
|
||||||
|
|
||||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
||||||
__pypackages__/
|
|
||||||
|
|
||||||
# Celery stuff
|
|
||||||
celerybeat-schedule
|
|
||||||
celerybeat.pid
|
|
||||||
|
|
||||||
# SageMath parsed files
|
|
||||||
*.sage.py
|
|
||||||
|
|
||||||
# Environments
|
|
||||||
.env
|
|
||||||
.venv
|
|
||||||
env/
|
|
||||||
venv/
|
|
||||||
ENV/
|
|
||||||
env.bak/
|
|
||||||
venv.bak/
|
|
||||||
|
|
||||||
# Spyder project settings
|
|
||||||
.spyderproject
|
|
||||||
.spyproject
|
|
||||||
|
|
||||||
# Rope project settings
|
|
||||||
.ropeproject
|
|
||||||
|
|
||||||
# mkdocs documentation
|
|
||||||
/site
|
|
||||||
|
|
||||||
# mypy
|
|
||||||
.mypy_cache/
|
|
||||||
.dmypy.json
|
|
||||||
dmypy.json
|
|
||||||
|
|
||||||
# Pyre type checker
|
|
||||||
.pyre/
|
|
||||||
|
|
||||||
# pytype static type analyzer
|
|
||||||
.pytype/
|
|
||||||
|
|
||||||
# Cython debug symbols
|
|
||||||
cython_debug/
|
|
||||||
|
|
||||||
# PyCharm
|
|
||||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
||||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
||||||
#.idea/
|
|
||||||
bin/
|
|
||||||
include/
|
|
||||||
lib64/
|
|
||||||
pyvenv.cfg
|
|
||||||
*.m4a
|
|
||||||
*.mp4
|
|
||||||
.env
|
|
||||||
done.*
|
|
|
@ -1,21 +0,0 @@
|
||||||
# poke-videobundler
|
|
||||||
|
|
||||||
Takes 2 input streams, downloads them, and spits out a combined file.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
1. Make sure `ffmpeg` and Python 3 are all installed.
|
|
||||||
2. Download the program files to your computer - `main.py` and `.env.example`.
|
|
||||||
3. Run `python3 -m pip install aiohttp`.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
1. `python3 main.py`.
|
|
||||||
2. If everything went well, you shouldn't see any output at launch.
|
|
||||||
3. You will now be able to call the server at :3030.
|
|
||||||
|
|
||||||
## Endpoints
|
|
||||||
|
|
||||||
- `/`: Will return `{success:true}` if alive.
|
|
||||||
- `/[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,104 +0,0 @@
|
||||||
import asyncio
|
|
||||||
import aiohttp
|
|
||||||
from aiohttp import web
|
|
||||||
import string
|
|
||||||
import os
|
|
||||||
import random
|
|
||||||
import subprocess
|
|
||||||
from aiohttp.web import Response, FileResponse
|
|
||||||
|
|
||||||
app = web.Application()
|
|
||||||
app.router._frozen = False
|
|
||||||
|
|
||||||
def get_random_string(length):
|
|
||||||
# choose from all lowercase letter
|
|
||||||
letters = string.ascii_lowercase
|
|
||||||
result_str = "".join(random.choice(letters) for i in range(length))
|
|
||||||
return result_str
|
|
||||||
|
|
||||||
async def run_command(cmd):
|
|
||||||
# Create subprocess
|
|
||||||
process = await asyncio.create_subprocess_shell(
|
|
||||||
cmd,
|
|
||||||
stdout=asyncio.subprocess.PIPE,
|
|
||||||
)
|
|
||||||
# Wait for the subprocess to finish
|
|
||||||
stdout, stderr = await process.communicate()
|
|
||||||
# Check for errors
|
|
||||||
if process.returncode!= 0:
|
|
||||||
# Log or handle the error
|
|
||||||
print(f"Command '{args}' failed with return code {process.returncode}")
|
|
||||||
return None
|
|
||||||
# Decode stdout and return
|
|
||||||
return stdout
|
|
||||||
|
|
||||||
async def merge(request: aiohttp.web.Request):
|
|
||||||
# register params
|
|
||||||
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"]
|
|
||||||
# validate
|
|
||||||
if " " in video_id or len(video_id) > 11:
|
|
||||||
print(f"Video {video_id} flagged as invalid, dropping request")
|
|
||||||
return
|
|
||||||
if not audio_itag.isdigit():
|
|
||||||
print(f"Audio itag {audio_itag} flagged as invalid, dropping request")
|
|
||||||
return
|
|
||||||
if not video_itag.isdigit():
|
|
||||||
print(f"Video itag {video_itag} flagged as invalid, dropping request")
|
|
||||||
return
|
|
||||||
if "Firefox" in request.headers["User-Agent"]:
|
|
||||||
# Sane browser that supports streaming
|
|
||||||
|
|
||||||
cmdline = f"ffmpeg -i \"https://eu-proxy.poketube.fun/latest_version?id={video_id}&itag={audio_itag}&local=true\" -i \"https://eu-proxy.poketube.fun/latest_version?id={video_id}&itag={video_itag}&local=true\" -c copy -f mp4 -movflags frag_keyframe+empty_moov -"
|
|
||||||
process = await asyncio.create_subprocess_shell(
|
|
||||||
cmdline,
|
|
||||||
stdout=asyncio.subprocess.PIPE,
|
|
||||||
stderr=asyncio.subprocess.PIPE
|
|
||||||
)
|
|
||||||
response = web.StreamResponse(status=206, reason='OK', headers={
|
|
||||||
'Content-Type': 'application/octet-stream',
|
|
||||||
'Transfer-Encoding': 'chunked',
|
|
||||||
'Content-Disposition': 'inline'
|
|
||||||
})
|
|
||||||
await response.prepare(request)
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
chunk = await process.stdout.readline()
|
|
||||||
if not chunk:
|
|
||||||
break
|
|
||||||
await response.write(chunk)
|
|
||||||
except Exception as e:
|
|
||||||
|
|
||||||
print(f"Error streaming FFmpeg output: {e}")
|
|
||||||
#finally:
|
|
||||||
#await response.write_eof()
|
|
||||||
else:
|
|
||||||
# Likely to be chromium browser, so to avoid browser shitting itself we download file
|
|
||||||
job_id = f'{request.rel_url.query["id"]}_{request.rel_url.query["audio_itag"]}_{request.rel_url.query["video_itag"]}'
|
|
||||||
if os.path.isfile(f"{job_id}.mp4"):
|
|
||||||
return web.FileResponse(
|
|
||||||
path=f"{job_id}.mp4"
|
|
||||||
)
|
|
||||||
cmdline = f"ffmpeg -i \"https://eu-proxy.poketube.fun/latest_version?id={video_id}&itag={audio_itag}&local=true\" -i \"https://eu-proxy.poketube.fun/latest_version?id={video_id}&itag={video_itag}&local=true\" -c:v copy -f mp4 -movflags frag_keyframe+empty_moov {job_id}.mp4"
|
|
||||||
process = await asyncio.create_subprocess_shell(
|
|
||||||
cmdline
|
|
||||||
)
|
|
||||||
await process.wait()
|
|
||||||
if process.returncode != 0: # Log or handle the error
|
|
||||||
return None
|
|
||||||
response = FileResponse(path=f"{job_id}.mp4")
|
|
||||||
return response
|
|
||||||
|
|
||||||
async def ping(request):
|
|
||||||
return web.Response(body='{"success": true}', content_type="application/json")
|
|
||||||
|
|
||||||
async def init_app():
|
|
||||||
app.router.add_get("/{id:.+}", merge)
|
|
||||||
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