This commit is contained in:
yair-mantis 2024-06-02 01:14:24 +03:00
parent 713ab9c44a
commit 54e2cd0714
3 changed files with 96 additions and 51 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
venv/ venv/
node_modules/ node_modules/
media/

130
main.py
View File

@ -2,39 +2,110 @@ from fastapi import FastAPI, HTTPException
from pydantic import BaseModel from pydantic import BaseModel
import yt_dlp import yt_dlp
import vlc import vlc
import threading import os
import time import json
app = FastAPI() app = FastAPI()
# Define a data model for the queue item # Define a data model for the queue item
class VideoLink(BaseModel): class VideoLink(BaseModel):
url: str url: str
# Create media directory if it doesn't exist
MEDIA_DIR = 'media'
if not os.path.exists(MEDIA_DIR):
os.makedirs(MEDIA_DIR)
# Queue to store video URLs # File to store video info dictionaries
video_queue = [] INFO_FILE = os.path.join(MEDIA_DIR, 'downloaded_info.json')
current_video = None try:
if os.path.exists(INFO_FILE) and os.path.getsize(INFO_FILE) > 0:
with open(INFO_FILE, 'r') as f:
downloaded_info = json.load(f)
else:
downloaded_info = {}
except (json.JSONDecodeError, IOError) as e:
downloaded_info = {}
# VLC player instance # VLC player instance
vlc_instance = vlc.Instance() vlc_instance = vlc.Instance('--quiet')
player = vlc_instance.media_player_new() player = vlc_instance.media_player_new()
player.set_fullscreen(True) playlist = []
# Function to download video or use existing file
def get_media_file(url):
ydl_opts = {
'format': 'best',
'quiet': True,
'outtmpl': os.path.join(MEDIA_DIR, '%(title)s.%(ext)s'),
'overwrites': False,
# 'verbose': True
}
# Add video URL to the queue with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info_dict = ydl.extract_info(url, download=False)
video_id = info_dict['id']
# Check if video ID already exists in downloaded info
if video_id in downloaded_info:
print(f"\nVideo {video_id} already downloaded\n\n")
video_file = downloaded_info[video_id]['filepath']
else:
print(f"\nDownloading video {video_id}\n\n")
video_file = ydl.prepare_filename(info_dict) # Fixed line
ydl.download([url])
minimal_info_dict = {
'id': video_id,
'title': info_dict['title'],
# 'release_date': info_dict.get('release_date'),
'filepath': video_file
}
downloaded_info[video_id] = minimal_info_dict
with open(INFO_FILE, 'w') as f:
json.dump(downloaded_info, f, indent=4)
return video_file
# Function to add video to VLC playlist
def add_to_playlist(url):
video_file = get_media_file(url)
media = vlc_instance.media_new_path(video_file)
playlist.append(media)
# Function to play the next video in the playlist
def play_next():
if playlist:
media = playlist.pop(0)
player.set_media(media)
player.play()
# Add video URL to the playlist
@app.post("/add") @app.post("/add")
def add_video(video_link: VideoLink): def add_video(video_link: VideoLink):
video_queue.append(video_link.url) add_to_playlist(video_link.url)
return {"message": "Video added to the queue"} if player.get_state() not in [vlc.State.Playing, vlc.State.Paused]:
play_next()
return {"message": "Video added to the playlist"}
# Remove video URL from the playlist
@app.delete("/remove/{index}")
def remove_video(index: int):
if 0 <= index < len(playlist):
removed_video = playlist.pop(index)
return {"message": "Video removed from the playlist", "url": removed_video.get_mrl()}
else:
raise HTTPException(status_code=404, detail="Index out of range")
# Get current queue # Skip current video and play next
@app.get("/queue") @app.post("/skip")
def get_queue(): def skip_video():
return {"queue": video_queue} player.stop()
play_next()
return {"message": "Skipped to the next video"}
# Get current playlist
@app.get("/playlist")
def get_playlist():
return {"playlist": [media.get_mrl() for media in playlist]}
# Control playback: play, pause, stop # Control playback: play, pause, stop
@app.post("/control/{action}") @app.post("/control/{action}")
@ -47,11 +118,6 @@ def control_playback(action: str):
player.stop() player.stop()
elif action == "mute": elif action == "mute":
player.audio_toggle_mute() player.audio_toggle_mute()
elif action == "fullscreen":
if player.get_fullscreen():
player.set_fullscreen(False)
else:
player.set_fullscreen(True)
else: else:
raise HTTPException(status_code=400, detail="Invalid action") raise HTTPException(status_code=400, detail="Invalid action")
return {"message": f"Player action {action} executed"} return {"message": f"Player action {action} executed"}
@ -62,29 +128,7 @@ def seek(seconds: int):
player.set_time(seconds * 1000) player.set_time(seconds * 1000)
return {"message": f"Seeked to {seconds} seconds"} return {"message": f"Seeked to {seconds} seconds"}
# Function to play videos from the queue
def play_videos():
global current_video
while True:
if video_queue and player.get_state() not in [vlc.State.Playing, vlc.State.Paused]:
current_video = video_queue.pop(0)
ydl_opts = {'format': 'best', 'quiet': True}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info_dict = ydl.extract_info(current_video, download=False)
video_url = info_dict.get("url", None)
media = vlc_instance.media_new(video_url)
player.set_media(media)
player.play()
time.sleep(1) # Give some time for the player to start
time.sleep(1)
# Start the video playing thread
video_thread = threading.Thread(target=play_videos, daemon=True)
video_thread.start()
# Run FastAPI # Run FastAPI
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn
uvicorn.run(app, host="127.0.0.1", port=1337) uvicorn.run(app, host="0.0.0.0", port=1337)

View File

@ -35,9 +35,9 @@ Your SpaceInvaderz API should now be running on `http://0.0.0.0:1337`.
## 🌌 API Endpoints ## 🌌 API Endpoints
### 1. Add Video to Queue ### 1. Add Video to playlist
**Description:** Adds a video to the playback queue. **Description:** Adds a video to the playback playlist.
- **URL:** `/add` - **URL:** `/add`
- **Method:** `POST` - **Method:** `POST`
@ -59,21 +59,21 @@ Invoke-RestMethod -Uri http://localhost:1337/add -Method Post -Body (@{url = $vi
curl -X POST "http://localhost:1337/add" -H "Content-Type: application/json" -d "{\"url\":\"YOUR_VIDEO_URL\"}" curl -X POST "http://localhost:1337/add" -H "Content-Type: application/json" -d "{\"url\":\"YOUR_VIDEO_URL\"}"
``` ```
### 2. Get Current Queue ### 2. Get Current playlist
**Description:** Retrieves the current queue of videos. **Description:** Retrieves the current playlist of videos.
- **URL:** `/queue` - **URL:** `/playlist`
- **Method:** `GET` - **Method:** `GET`
#### PowerShell: #### PowerShell:
```powershell ```powershell
Invoke-RestMethod -Uri http://localhost:1337/queue -Method Get Invoke-RestMethod -Uri http://localhost:1337/playlist -Method Get
``` ```
#### cURL: #### cURL:
```sh ```sh
curl -X GET "http://localhost:1337/queue" curl -X GET "http://localhost:1337/playlist"
``` ```
### 3. Control Playback ### 3. Control Playback