我正在尝试使用 winmm.dll (ctypes.windll.winmm( 在 python 中播放.mp3文件。但是当我尝试以毫秒为单位获取某个文件的长度而不是实际长度(05:23 = 大约 323000 毫秒(时,我只得到 3。状态命令获取的时间格式为"m",设置命令后不会改变。下面是一些说明该问题的代码:
from ctypes import windll, c_buffer
fp = 'song.mp3'
alias = 'test'
buf = c_buffer(255)
r = windll.winmm.mciSendStringW(f'open "{fp}" alias {alias}', buf, 254, 0)
print(r)
buf = c_buffer(255)
r = windll.winmm.mciSendStringW(f'status {alias} time format', buf, 254, 0)
print(r, buf.value)
buf = c_buffer(255)
r = windll.winmm.mciSendStringW(f'set {alias} time format milliseconds', buf, 254, 0)
print(r)
buf = c_buffer(255)
r = windll.winmm.mciSendStringW(f'status {alias} time format', buf, 254, 0)
print(r, buf.value)
buf = c_buffer(255)
r = windll.winmm.mciSendStringW(f'status {alias} length', buf, 254, 0)
print(r, buf.value)
及其输出:
0
0 b'm'
0
0 b'm'
0 b'3'
提前感谢您的帮助!
正如我在评论中指定的,这是一个经典的未定义行为示例。检查 [SO]:通过 ctypes 从 Python 调用的 C 函数返回不正确的值(@CristiFati 的答案(以获取更多详细信息。
此外,您正在混合8位和16 位字符串。
列出 [Python 3.Docs]: ctypes - Python 的外部函数库。
code00.py:
#!/usr/bin/env python3
import sys
import ctypes as ct
from ctypes import wintypes as wt
def main(*argv):
winmm_dll = ct.WinDLL("Winmm.dll")
mciSendString = winmm_dll.mciSendStringW
mciSendString.argtypes = (wt.LPCWSTR, wt.LPWSTR, wt.UINT, wt.HANDLE)
mciSendString.restype = wt.DWORD
file_name = "./SampleAudio_0.4mb.mp3" # Downloaded from https://www.sample-videos.com/audio/mp3/crowd-cheering.mp3
alias_name = "test00"
status_commands = [
f"status {alias_name} time format",
f"status {alias_name} length",
]
commands = [f"open "{file_name}" alias {alias_name}"]
commands.extend(status_commands)
commands.append(f"set {alias_name} time format ms")
commands.extend(status_commands)
commands.append(f"close {alias_name}")
out_buf_len = 0xFF
out_buf = ct.create_unicode_buffer(out_buf_len)
for command in commands:
print(f"Sending {command}...")
res = mciSendString(command, out_buf, out_buf_len, None)
print(f" Result: {res}n Output: {out_buf.value}")
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}n".format(" ".join(item.strip() for item in sys.version.split("n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main(*sys.argv[1:])
print("nDone.")
输出:
[cfati@CFATI-5510-0:e:WorkDevStackOverflowq059343461]> "e:WorkDevVEnvspy_064_03.07.03_test0Scriptspython.exe" code00.py Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32 Sending open "./SampleAudio_0.4mb.mp3" alias test00... Result: 0 Output: 1 Sending status test00 time format... Result: 0 Output: milliseconds Sending status test00 length... Result: 0 Output: 27746 Sending set test00 time format ms... Result: 0 Output: Sending status test00 time format... Result: 0 Output: milliseconds Sending status test00 length... Result: 0 Output: 27746 Sending close test00... Result: 0 Output: Done.