在 Windows 上获取当前正在播放的媒体缩略图的方法仅对每个 Python 实例有效一次
Approach to get currently playing media's thumbnail on Windows only works once per Python instance
我正在尝试获取 windows 上当前正在播放的媒体的缩略图,多亏了这个答案 (),我得到了相当多的帮助,但是我遇到了一个奇怪的问题在 get_thumbnail()
中,变量 byte_buffer
总是在第一个 运行 之后最终成为 0
的长度...就像我第一次调用它一样,我完美地取回了缩略图,但所有进一步的调用最终都失败了...
这是我目前拥有的:
from winrt.windows.media.control import GlobalSystemMediaTransportControlsSessionManager as MediaManager
from winrt.windows.storage.streams import DataReader, Buffer, InputStreamOptions
from io import BytesIO
from PIL import Image
import asyncio
async def get_thumbnail():
sessions = await MediaManager.request_async()
current_session = sessions.get_current_session()
if current_session:
properties = await current_session.try_get_media_properties_async()
media_info = {song_attr: properties.__getattribute__(song_attr) for song_attr in dir(properties) if song_attr[0] != '_'}
if media_info.get('thumbnail'):
thumb_stream_ref = media_info['thumbnail']
thumb_read_buffer = Buffer(5000000)
readable_stream = await thumb_stream_ref.open_read_async()
readable_stream.read_async(thumb_read_buffer, thumb_read_buffer.capacity, InputStreamOptions.READ_AHEAD)
buffer_reader = DataReader.from_buffer(thumb_read_buffer)
byte_buffer = buffer_reader.read_bytes(thumb_read_buffer.length)
binary = BytesIO()
binary.write(bytearray(byte_buffer))
binary.seek(0)
print(len(bytearray(byte_buffer)))
img = Image.open(binary)
return img
thumbnail = asyncio.run(get_thumbnail())
thumbnail.show()
# This will work
thumbnail2 = asyncio.run(get_thumbnail())
thumbnail2.show()
# This will not
示例输出:
C:\Users\willy\Desktop>test.py
117672
0
Traceback (most recent call last):
File "C:\Users\willy\Desktop\test.py", line 39, in <module>
thumbnail2 = asyncio.run(get_thumbnail())
File "C:\Python38\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
File "C:\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
return future.result()
File "C:\Users\willy\Desktop\test.py", line 31, in get_thumbnail
img = Image.open(binary)
File "C:\Python38\lib\site-packages\PIL\Image.py", line 2930, in open
raise UnidentifiedImageError(
PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x00000278D2FB3B30>
解决方案
只需等待 readable_stream.read_async(...)
调用的结果:
...
readable_stream = await thumb_stream_ref.open_read_async()
await readable_stream.read_async(thumb_read_buffer, thumb_read_buffer.capacity, InputStreamOptions.READ_AHEAD)
buffer_reader = DataReader.from_buffer(thumb_read_buffer)
...
缩略图现在应该每次都能成功显示。
调试过程
(对于任何感兴趣的人和未来类似的错误)
在对您的代码进行断点后,似乎在第二次调用 get_thumbnail()
时,byte_buffer
为空。这表明 thumb_read_buffer
没有从流中正确填充。
有趣的是,当单步执行代码时,图像显示了两次。这向我暗示,也许没有等待异步函数调用。
原来.read_async()
(顾名思义就是函数名)是winrt中的异步操作(见IInputStream.ReadAsync on docs.microsoft.com)。因此,等待其执行解决了空 thumb_read_buffer
.
的问题
我正在尝试获取 windows 上当前正在播放的媒体的缩略图,多亏了这个答案 (get_thumbnail()
中,变量 byte_buffer
总是在第一个 运行 之后最终成为 0
的长度...就像我第一次调用它一样,我完美地取回了缩略图,但所有进一步的调用最终都失败了...
这是我目前拥有的:
from winrt.windows.media.control import GlobalSystemMediaTransportControlsSessionManager as MediaManager
from winrt.windows.storage.streams import DataReader, Buffer, InputStreamOptions
from io import BytesIO
from PIL import Image
import asyncio
async def get_thumbnail():
sessions = await MediaManager.request_async()
current_session = sessions.get_current_session()
if current_session:
properties = await current_session.try_get_media_properties_async()
media_info = {song_attr: properties.__getattribute__(song_attr) for song_attr in dir(properties) if song_attr[0] != '_'}
if media_info.get('thumbnail'):
thumb_stream_ref = media_info['thumbnail']
thumb_read_buffer = Buffer(5000000)
readable_stream = await thumb_stream_ref.open_read_async()
readable_stream.read_async(thumb_read_buffer, thumb_read_buffer.capacity, InputStreamOptions.READ_AHEAD)
buffer_reader = DataReader.from_buffer(thumb_read_buffer)
byte_buffer = buffer_reader.read_bytes(thumb_read_buffer.length)
binary = BytesIO()
binary.write(bytearray(byte_buffer))
binary.seek(0)
print(len(bytearray(byte_buffer)))
img = Image.open(binary)
return img
thumbnail = asyncio.run(get_thumbnail())
thumbnail.show()
# This will work
thumbnail2 = asyncio.run(get_thumbnail())
thumbnail2.show()
# This will not
示例输出:
C:\Users\willy\Desktop>test.py
117672
0
Traceback (most recent call last):
File "C:\Users\willy\Desktop\test.py", line 39, in <module>
thumbnail2 = asyncio.run(get_thumbnail())
File "C:\Python38\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
File "C:\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
return future.result()
File "C:\Users\willy\Desktop\test.py", line 31, in get_thumbnail
img = Image.open(binary)
File "C:\Python38\lib\site-packages\PIL\Image.py", line 2930, in open
raise UnidentifiedImageError(
PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x00000278D2FB3B30>
解决方案
只需等待 readable_stream.read_async(...)
调用的结果:
...
readable_stream = await thumb_stream_ref.open_read_async()
await readable_stream.read_async(thumb_read_buffer, thumb_read_buffer.capacity, InputStreamOptions.READ_AHEAD)
buffer_reader = DataReader.from_buffer(thumb_read_buffer)
...
缩略图现在应该每次都能成功显示。
调试过程
(对于任何感兴趣的人和未来类似的错误)
在对您的代码进行断点后,似乎在第二次调用 get_thumbnail()
时,byte_buffer
为空。这表明 thumb_read_buffer
没有从流中正确填充。
有趣的是,当单步执行代码时,图像显示了两次。这向我暗示,也许没有等待异步函数调用。
原来.read_async()
(顾名思义就是函数名)是winrt中的异步操作(见IInputStream.ReadAsync on docs.microsoft.com)。因此,等待其执行解决了空 thumb_read_buffer
.