11import asyncio
2+ import base64
23import json
34import os
45import pathlib
56import re
67import shutil
8+ import struct
79from typing import AsyncGenerator , Any
810
911def _is_playlist_url (url : str ) -> bool :
@@ -104,7 +106,7 @@ async def _spotiflac_stream(
104106 yield f"data: Output folder : { dest_note } \n \n "
105107 yield f"data: $ { ' ' .join (command )} \n \n "
106108 yield "data: \n \n "
107- yield "data: ⏳ SpotiFLAC is running. Output may appear in batches — this is normal for the binary.\n \n "
109+ yield "data: ⏳ SpotiFLAC is running. Output may appear in batches - this is normal for the binary.\n \n "
108110
109111 # Attempt to find playlist title (unlikely)
110112 if is_playlist and playlist_folder :
@@ -216,6 +218,7 @@ async def _spotiflac_stream(
216218 else : # opus
217219 ffmpeg_cmd = [
218220 "ffmpeg" , "-y" , "-i" , str (flac_path ),
221+ "-vn" ,
219222 "-map_metadata" , "0" ,
220223 "-c:a" , "libopus" ,
221224 "-b:a" , "320k" ,
@@ -230,6 +233,40 @@ async def _spotiflac_stream(
230233 )
231234 await proc .wait ()
232235 if proc .returncode == 0 :
236+ # Embed cover art for opus via mutagen
237+ if output_format == "opus" :
238+ try :
239+ from mutagen .flac import FLAC
240+ from mutagen .oggopus import OggOpus
241+
242+ flac_tags = FLAC (str (flac_path ))
243+ if flac_tags .pictures :
244+ pic = flac_tags .pictures [0 ]
245+
246+ # Build METADATA_BLOCK_PICTURE binary structure
247+ mime = pic .mime .encode ("utf-8" )
248+ desc = pic .desc .encode ("utf-8" )
249+ data = pic .data
250+
251+ block = struct .pack (">I" , pic .type )
252+ block += struct .pack (">I" , len (mime )) + mime
253+ block += struct .pack (">I" , len (desc )) + desc
254+ block += struct .pack (
255+ ">IIIII" ,
256+ pic .width , pic .height ,
257+ pic .depth , pic .colors ,
258+ len (data )
259+ )
260+ block += data
261+
262+ ogg = OggOpus (str (out_path ))
263+ ogg ["metadata_block_picture" ] = [
264+ base64 .b64encode (block ).decode ("ascii" )
265+ ]
266+ ogg .save ()
267+ except Exception as cover_err :
268+ yield f"data: ⚠️ Cover art embedding failed (file is still OK): { cover_err } \n \n "
269+
233270 flac_path .unlink () # Delete original FLAC
234271 transcoded += 1
235272 else :
0 commit comments