【WMA 文件的研究结果一】WM/Lyrics_Synchronised 标签属性(同步显示歌词)

本文介绍WMFSDK11中同步歌词的数据结构WM_SYNCHRONISED_LYRICS,详细解释了时间戳格式、内容类型等字段,并展示了如何通过这些数据获取同步歌词。

这里需要说明的是:一般的播放器用的是 Lyric 文件格式,对应的标签是 WM/Lyrics.
WM/Lyrics 是属于 WMT_TYPE_STRING

而这里说的并非这个。
在WMF SDK 11中:

typedef struct _WMSynchronisedLyrics{
   BYTE    bTimeStampFormat;
   BYTE    bContentType;
   LPWSTR pwszContentDescriptor;
   DWORD   dwLyricsLen;
   BYTE*   pbLyrics;
} WM_SYNCHRONISED_LYRICS;

 

所属类型是:WMT_TYPE_BINARY
其中:
bTimeStampFormat: (时间戳标识)

Value Description
1Time stamps are 32-bit values containing the absolute time of the lyric in frame numbers.
2Time stamps are 32-bit values containing the absolute time of the lyric in milliseconds.

bContentType: (内容类型)
BYTE specifying the type of synchronized strings that are in the lyrics data. Set to one of the following values.

Value Description
0Synchronized strings other than the types listed in this table
1Song lyrics
2Text transcription
3Names of parts of the content. For example, movements of classical pieces, like "Adagio"
4Events, such as stage directions in operas
5Chord notations
6Trivia information
7URLs to Web pages
8URLs to images

pwszContentDescriptor :(内容说明)
指针,指向宽字符,以 null 结尾。
dwLyricsLen :(歌词内容的长度)
pbLyrics: (歌词)

调用函数取得所返回值得到如图所示:
  http://hi.youkuaiyun.com/attachment/201001/21/1188217_1264044160PNpl.jpg

其他的很清楚,不多说,这里只说其中 pwszContentDescriptor 的长度的计算:
假设其长度为:Len
Len = 70 27 AD 00 (转为十进制整数) - 5E 27 AD 00 (转为十进制整数)
就是pwszContentDescriptor 长度了。这里的值是:
Len = 11347824 - 11347806
结果为:18 , 与图正确对应!
类推直接得出dwLyricsLen 的数值。

下面说 pbLyrics ,如图所示:
  http://hi.youkuaiyun.com/attachment/201001/21/1188217_1264044160NSkk.jpg

浅黄色代表的是歌词,
红色是时间:
bTimeStampFormat=2 的话 毫秒为单位,
bTimeStampFormat=1 的话,帧数号为单位,
如此不断的依次排列,只要得到这两个值就可以得到同步歌词了。

时间同步脚本如下#!/bin/bash # K8s集群离线时间同步脚本 # 使用chrony作为NTP服务 set -e # 配置参数 CHRONY_CONF="/etc/chrony.conf" CHRONY_SERVICE="chronyd" # 同步时间函数 sync_time() { echo "正在启动时间同步服务..." # 重启chronyd服务 systemctl restart "${CHRONY_SERVICE}" || { echo "错误: 无法启动chronyd服务" return 1 } # 等待服务稳定 sleep 2 # 检查服务状态 if ! systemctl is-active --quiet "${CHRONY_SERVICE}"; then echo "错误: chronyd服务未正常运行" return 1 fi # 强制立即同步 echo "强制时间同步..." chronyc makestep >/dev/null 2>&1 || true # 显示同步状态 echo "时间同步状态:" chronyc sources -v chronyc tracking return 0 } # 配置Master节点 setup_master() { echo "配置Master节点为时间服务器..." # 备份原配置 cp -f "${CHRONY_CONF}" "${CHRONY_CONF}.bak" # 创建新配置 cat > "${CHRONY_CONF}" << EOF # K8s集群Master时间服务器配置 server 127.127.1.0 iburst local stratum 10 allow 192.168.1.0/24 logdir /var/log/chrony driftfile /var/lib/chrony/drift makestep 1.0 3 rtcsync EOF # 启用并启动服务 systemctl enable "${CHRONY_SERVICE}" >/dev/null 2>&1 # 同步时间 sync_time } # 配置Worker节点 setup_worker() { local master_ip=$1 echo "配置Worker节点连接到Master: ${master_ip}..." # 备份原配置 cp -f "${CHRONY_CONF}" "${CHRONY_CONF}.bak" # 创建新配置 cat > "${CHRONY_CONF}" << EOF # K8s集群Worker时间客户端配置 server ${master_ip} iburst driftfile /var/lib/chrony/drift makestep 1.0 3 rtcsync logdir /var/log/chrony EOF # 启用并启动服务 systemctl enable "${CHRONY_SERVICE}" >/dev/null 2>&1 # 同步时间 sync_time } # 主函数 main() { # 检查root权限 if [ "$(id -u)" != "0" ]; then echo "错误: 必须使用root权限运行此脚本" exit 1 fi # 检查chrony是否安装 if ! command -v chronyc >/dev/null 2>&1; then echo "错误: chrony未安装,请先安装chrony" exit 1 fi # 解析参数 case "$1" in master) setup_master ;; worker) if [ -z "$2" ]; then echo "用法: $0 worker <MASTER_IP>" exit 1 fi setup_worker "$2" ;; *) echo "用法: $0 <master|worker> [MASTER_IP]" echo "示例:" echo " Master节点: $0 master" echo " Worker节点: $0 worker 192.168.1.100" exit 1 ;; esac echo "时间同步配置完成!" } main "$@" setup_time_sync() { # 明确职责:主脚本负责调用Master上已有的脚本并分发到Worker # 前提:time-sync.sh已存在于Master节点的/root目录下 local master_ip="${M[0]}" local script_name="time-sync.sh" local lock_file="/tmp/time_sync.lock" # 防止重复执行的锁机制 if [ -f "$lock_file" ]; then echo "时间同步配置正在进行中,已存在锁定文件: $lock_file" return 0 fi touch "$lock_file" echo "=== 开始配置时间同步(主脚本负责调度)===" # 检查Master节点上是否已存在脚本 echo "检查Master节点上的脚本..." if ! ssh -o StrictHostKeyChecking=no root@$master_ip "[ -f /root/$script_name ]"; then echo "错误:Master节点上未找到$script_name" echo "请先确保脚本已存在于Master节点的/root目录" rm -f "$lock_file" return 1 fi echo "✓ Master节点上存在$script_name" # 配置Master节点(使用本地已有的脚本) echo "在Master节点执行配置..." ssh -o StrictHostKeyChecking=no root@$master_ip " chmod +x /root/$script_name && /root/$script_name master " || { echo "Master配置失败" rm -f "$lock_file" return 1 } echo "✓ Master节点配置完成" # 处理Worker节点 local workers=("${W[@]}" "${D[@]}" "${L[@]}") for node in "${workers[@]}"; do echo "处理Worker节点: $node" # 从Master分发脚本到Worker(使用Master上已有的脚本) ssh -o StrictHostKeyChecking=no root@$master_ip " scp /root/$script_name root@$node:/root/ " || { echo "脚本分发到$node失败" continue } # 配置Worker节点 ssh -o StrictHostKeyChecking=no root@$master_ip " ssh -o StrictHostKeyChecking=no root@$node ' chmod +x /root/$script_name && /root/$script_name worker $master_ip ' " || { echo "$node配置失败" continue } echo "✓ $node配置完成" done echo "=== 所有节点时间同步配置完成 ===" rm -f "$lock_file" return 0 }这个是时间同步函数,两个配合起来就是不行出现 处理Worker节点: 192.168.7.5 配置Worker节点连接到Master: 192.168.7.1... 正在启动时间同步服务... 强制时间同步... 时间同步状态: .-- Source mode '^' = server, '=' = peer, '#' = local clock. / .- Source state '*' = current best, '+' = combined, '-' = not combined, | / 'x' = may be in error, '~' = too variable, '?' = unusable. || .- xxxx [ yyyy ] +/- zzzz || Reachability register (octal) -. | xxxx = adjusted offset, || Log2(Polling interval) --. | | yyyy = measured offset, || \ | | zzzz = estimated error. || | | \ MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^? _gateway 0 6 0 - +0ns[ +0ns] +/- 0ns Reference ID : 00000000 () Stratum : 0 Ref time (UTC) : Thu Jan 01 00:00:00 1970 System time : 0.000000000 seconds slow of NTP time Last offset : +0.000000000 seconds RMS offset : 0.000000000 seconds Frequency : 14.605 ppm slow Residual freq : +0.000 ppm Skew : 0.000 ppm Root delay : 1.000000000 seconds Root dispersion : 1.000000000 seconds Update interval : 0.0 seconds Leap status : Not synchronised 时间同步配置完成! ✓ 192.168.7.5配置完成 === 所有节点时间同步配置完成 === [root@localhost script]# date Wed Sep 24 02:43:42 PM CST 2025 [root@localhost script]# ssh 192.168.7.5 Last login: Wed Oct 2 18:22:33 2024 from 192.168.7.1 mem:[7.0%] swap:[0.0%] disk:[2%] IP1:[192.168.7.5] IP2:[172.17.0.1] [root@localhost ~]# date Wed Oct 2 07:04:18 PM CST 2024 [root@localhost ~]# [root@localhost ~]# [root@localhost ~]# [root@localhost ~]# date Wed Oct 2 07:04:36 PM CST 2024 [root@localhost ~]# exit logout Connection to 192.168.7.5 closed. [root@localhost script]# ssh 192.168.7.4 Last login: Mon Sep 15 10:08:27 2025 from 192.168.7.1 mem:[7.8%] swap:[0.0%] disk:[2%] IP1:[192.168.7.4] IP2:[192.168.19.21] IP3:[172.17.0.1] [root@localhost ~]# date Wed Sep 24 02:45:17 PM CST 2025 时间不同步问题,这个怎么解决?用shell脚本处理
09-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值