Working in a buggy state... but more or less working

This commit is contained in:
Christoph Stahl 2024-10-09 18:05:29 +02:00
parent fc9b79172a
commit 15cc8f8147
4 changed files with 49 additions and 48 deletions

View file

@ -37,6 +37,8 @@ import engineio
from PIL import Image from PIL import Image
from yaml import load, Loader from yaml import load, Loader
from syng.player_libmpv import Player
from . import jsonencoder from . import jsonencoder
from .entry import Entry from .entry import Entry
from .sources import configure_sources, Source from .sources import configure_sources, Source
@ -121,6 +123,7 @@ class Client:
self.sources = configure_sources(config["sources"]) self.sources = configure_sources(config["sources"])
self.state = State() self.state = State()
self.currentLock = asyncio.Semaphore(0) self.currentLock = asyncio.Semaphore(0)
self.player = Player()
self.register_handlers() self.register_handlers()
def register_handlers(self) -> None: def register_handlers(self) -> None:
@ -244,26 +247,7 @@ class Client:
:type entry: :py:class:`Entry` :type entry: :py:class:`Entry`
:rtype: None :rtype: None
""" """
background = Image.new("RGB", (1280, 720)) self.player.queue_next(entry)
subtitle: str = f"""1
00:00:00,00 --> 00:05:00,00
{entry.artist} - {entry.title}
{entry.performer}"""
with tempfile.NamedTemporaryFile() as tmpfile:
background.save(tmpfile, "png")
process = await asyncio.create_subprocess_exec(
"mpv",
tmpfile.name,
f"--image-display-duration={self.state.config['preview_duration']}",
"--sub-pos=50",
"--sub-file=-",
"--fullscreen",
self.state.config["mpv_options"],
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
await process.communicate(subtitle.encode())
async def handle_play(self, data: dict[str, Any]) -> None: async def handle_play(self, data: dict[str, Any]) -> None:
""" """
@ -293,7 +277,9 @@ class Client:
self.state.current_source = self.sources[entry.source] self.state.current_source = self.sources[entry.source]
if self.state.config["preview_duration"] > 0: if self.state.config["preview_duration"] > 0:
await self.preview(entry) await self.preview(entry)
await self.sources[entry.source].play(entry, self.state.config["mpv_options"]) await self.sources[entry.source].play(
entry, self.player, self.state.config["mpv_options"]
)
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
print_exc() print_exc()
self.state.current_source = None self.state.current_source = None

View file

@ -1,5 +1,6 @@
import sys
import tempfile import tempfile
from typing import Optional from typing import Iterable, Optional
from qrcode.main import QRCode from qrcode.main import QRCode
import mpv import mpv
import os import os
@ -64,16 +65,23 @@ class Player:
def queue_next(self, entry: Entry): def queue_next(self, entry: Entry):
self.play_image(f"{__dirname__}/static/background20perc.png", 3) self.play_image(f"{__dirname__}/static/background20perc.png", 3)
subtitle: str = f"""1
frame = sys._getframe()
stream_name = f"__python_mpv_play_generator_{hash(frame)}"
@self.mpv.python_stream(stream_name)
def preview() -> Iterable[bytes]:
subtitle: str = f"""1
00:00:00,00 --> 00:05:00,00 00:00:00,00 --> 00:05:00,00
{entry.artist} - {entry.title} {entry.artist} - {entry.title}
{entry.performer}""" {entry.performer}"""
with tempfile.NamedTemporaryFile(delete=False) as tmpfile: yield subtitle.encode()
print(tmpfile.name) preview.unregister()
tmpfile.write(subtitle.encode())
tmpfile.flush() self.mpv.sub_pos = 50
self.mpv.sub_pos = 50 self.mpv.sub_add(f"python://{stream_name}")
self.mpv.sub_add(tmpfile.name)
self.mpv.wait_for_property("eof-reached")
def play_image(self, image: str, duration: int): def play_image(self, image: str, duration: int):
self.mpv.image_display_duration = duration self.mpv.image_display_duration = duration
@ -86,3 +94,4 @@ class Player:
self.mpv.pause = True self.mpv.pause = True
self.mpv.play(video) self.mpv.play(video)
self.mpv.pause = False self.mpv.pause = False
self.mpv.wait_for_property("eof-reached")

View file

@ -21,6 +21,8 @@ from typing import Tuple
from typing import Type from typing import Type
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from syng.player_libmpv import Player
from ..log import logger from ..log import logger
from ..entry import Entry from ..entry import Entry
@ -271,7 +273,7 @@ class Source(ABC):
self.downloaded_files[entry.ident].ready.set() self.downloaded_files[entry.ident].ready.set()
async def play(self, entry: Entry, mpv_options: str) -> None: async def play(self, entry: Entry, player: Player, mpv_options: str) -> None:
""" """
Play the entry. Play the entry.
@ -302,13 +304,15 @@ class Source(ABC):
else self.extra_mpv_arguments else self.extra_mpv_arguments
) )
self.player = await self.play_mpv( # self.player = await self.play_mpv(
self.downloaded_files[entry.ident].video, # self.downloaded_files[entry.ident].video,
self.downloaded_files[entry.ident].audio, # self.downloaded_files[entry.ident].audio,
*extra_options, # *extra_options,
# )
player.play(
self.downloaded_files[entry.ident].video, self.downloaded_files[entry.ident].audio
) )
await self.player.communicate() # await self.player.wait()
await self.player.wait()
self.player = None self.player = None
if self._skip_next: if self._skip_next:
self._skip_next = False self._skip_next = False

View file

@ -18,6 +18,8 @@ from yt_dlp import YoutubeDL
from yt_dlp.utils import DownloadError from yt_dlp.utils import DownloadError
from platformdirs import user_cache_dir from platformdirs import user_cache_dir
from syng.player_libmpv import Player
from ..entry import Entry from ..entry import Entry
from ..result import Result from ..result import Result
@ -236,7 +238,7 @@ class YoutubeSource(Source):
""" """
return {"channels": self.channels} return {"channels": self.channels}
async def play(self, entry: Entry, mpv_options: str) -> None: async def play(self, entry: Entry, player: Player, mpv_options: str) -> None:
""" """
Play the given entry. Play the given entry.
@ -252,18 +254,18 @@ class YoutubeSource(Source):
:rtype: None :rtype: None
""" """
if self.start_streaming and not self.downloaded_files[entry.ident].complete: if self.start_streaming and not self.downloaded_files[entry.ident].complete:
self.player = await self.play_mpv( # self.player = await self.play_mpv(
entry.ident, # entry.ident,
None, # None,
"--script-opts=ytdl_hook-ytdl_path=yt-dlp,ytdl_hook-exclude='%.pls$'", # "--script-opts=ytdl_hook-ytdl_path=yt-dlp,ytdl_hook-exclude='%.pls$'",
f"--ytdl-format={self.formatstring}", # f"--ytdl-format={self.formatstring}",
"--fullscreen", # "--fullscreen",
mpv_options, # mpv_options,
) # )
await self.player.communicate() # await self.player.wait()
await self.player.wait() player.play(entry.ident)
else: else:
await super().play(entry, mpv_options) await super().play(entry, player, mpv_options)
async def get_entry( async def get_entry(
self, self,