HEVC视频编码格式与浏览器兼容性问题

问题

以下是ChatGPT的回复

HEVC (Main) 和 H.264 (High) 是两种不同的视频编码标准,它们有几个主要区别:

  1. 编码效率和压缩比
  • HEVC (H.265):比 H.264 更高效,能够在相同的视频质量下提供更低的比特率。换句话说,HEVC 可以在更小的文件大小下保持更好的画质。
  • H.264:相较于 HEVC,压缩效率较低,相同质量的视频会有较大的文件大小。
  1. 视频质量
  • HEVC:能够提供更高的压缩率和视频质量,特别是在高分辨率视频(如 4K)和低比特率的情况下表现更好。
  • H.264:虽然它也提供高质量的视频,但相对于 HEVC 来说,压缩率较低,可能在较低比特率下会出现更多的压缩损失或画质下降。
  1. 硬件支持
  • HEVC:因为 HEVC 比 H.264 更复杂,许多旧的硬件设备(如老款的电视、手机、平板等)可能不支持 HEVC 解码或编码,尤其是低端设备。
  • H.264:几乎所有设备和平台都支持 H.264,无论是硬件解码还是软件解码。
  1. 编码复杂度
  • HEVC:编码复杂度高,需要更多的计算资源来进行编码和解码,因此会消耗更多的 CPU 或 GPU 资源。
  • H.264:编码和解码相对简单,因此对于低功耗设备或实时视频流应用更为合适。
  1. 广泛应用
  • HEVC:主要用于高分辨率视频(如 4K 视频),而且在流媒体和广播等新兴领域越来越流行。
  • H.264:依然是网络视频流、视频会议、蓝光光盘等领域的主流编码格式。
  1. 兼容性
  • HEVC:新兴的编码格式,虽然它在压缩和质量上有优势,但老旧设备和浏览器的兼容性相对较差。
    • Linux(Ubuntu)的Chrome浏览器不支持
    • Windows/MacOS/Andriod都支持
  • H.264:几乎所有设备和平台都支持,兼容性最好。

浏览器适配方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>视频播放示例</title>
</head>
<body>
<h1>视频播放示例</h1>
<video id="video-player" controls width="640">
<!-- 默认的视频文件,支持 H.264 格式 -->
<source id="video-source" src="video_h264.mp4" type="video/mp4">
<!-- 如果浏览器支持 HEVC 格式,可以加载 HEVC 视频 -->
<source src="video_hevc.mp4" type="video/mp4; codecs=hevc">
<!-- 备用格式 WebM -->
<source src="video.webm" type="video/webm">
<!-- 如果浏览器不支持视频格式 -->
您的浏览器不支持视频播放,请更新浏览器或使用支持的视频格式。
</video>

<script>
var videoElement = document.getElementById('video-player');
var h264Support = videoElement.canPlayType('video/mp4; codecs="avc1.42E01E"');
var hevcSupport = videoElement.canPlayType('video/mp4; codecs="hevc"');

if (hevcSupport) {
// 如果支持 HEVC,则加载 HEVC 格式的视频
document.getElementById('video-source').src = 'video_hevc.mp4';
} else if (h264Support) {
// 如果支持 H.264,则加载 H.264 格式的视频
document.getElementById('video-source').src = 'video_h264.mp4';
} else {
// 如果两者都不支持,加载 WebM 格式
videoElement.innerHTML = '<source src="video.webm" type="video/webm">';
}
</script>
</body>
</html>

python3.13无GIL自由线程新特性

安装Python3.13.2

Windows: 安装python3.13, 直接下载即可,在安装目录的 python3.13t

  • 在”Advanced Options”下,确保选择“Download free-threaded binaries(experimental)”选项,然后点击“安装”

Ubuntu: 下载代码编译

1
2
3
4
5
6
7
8
./configure --disable-gil --enable-optimizations
make

# 会覆盖系统的python
make install

# 或者, 不覆盖系统的python
make altinstall

运行测试代码:

1
2
3
4
5
6
7
8
9
import threading


def f():
while 1:
pass

for i in range(16):
threading.Thread(target=f).start()

使用python3.13tpython3.13 运行代码 python3.13t test.pyPYTHON_GIL=0 python3.13 test.pypython3.13 -Xgil=0 test.py, 查看16核CPU的占用率100%

  • 如何没有设置 PYTHON_GIL, 那么 python3.13默认是无GIL的

  • 对比python3.13的无GIL版本:

  • 对比python3.13 的有GIL版本:

  • 对比python3.12版本(有GIL)

PEP-703

https://peps.python.org/pep-0703/

关于容器的线程安全

https://peps.python.org/pep-0703/#container-thread-safety

python底层的实现中,每个object内部使用临界区来实现线程同步

Per-object locks with critical sections provide weaker protections than the GIL. Because the GIL doesn’t necessarily ensure that concurrent operations are atomic or correct, the per-object locking scheme also cannot ensure that concurrent operations are atomic or correct. Instead, per-object locking aims for similar protections as the GIL, but with mutual exclusion limited to individual objects.

  • 在object加锁
    • list.append, list.insert, list.repeat, PyList_SetItem
    • dict.__setitem__, PyDict_SetItem
    • list.clear, dict.clear
    • list.__repr__, dict.__repr__, etc.
    • list.extend(iterable)
    • setiter_iternext
  • 在2个object加锁
    • list.extend(list), list.extend(set), list.extend (dictitems), and other specializations where the implementation is specialized for argument type.
    • list.concat(list)
    • list.__eq__(list), dict.__eq__(dict)
  • 无锁
    • len(list) i.e., list_length(PyListObject *a)
    • len(dict)
    • len(set)
  • 看情况, 需要根据内存分配器的实现而定, 尽量会少用锁提升性能
    • list[idx] (list_subscript)
    • dict[key] (dict_subscript)
    • listiter_next, dictiter_iternextkey/value/item
    • list.contains

no-GIL + async/await

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import threading
import asyncio
import time

async def async_range(n):
for i in range(n):
yield i

# 异步任务
async def async_task(name):
for i in range(20):
print(f"异步任务 {name} 开始执行")
async for i in async_range(1000_0000):
pass
print(f"异步任务 {name} 执行结束")
return f"结果 {name}"

# 在线程中运行异步任务
def run_async_in_thread(name):
# 创建一个新的事件循环
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

# 运行异步任务
result = loop.run_until_complete(async_task(name))

# 关闭事件循环
loop.close()

return result

# 线程函数
def thread_function(name):
print(f"线程 {name} 开始执行")
result = run_async_in_thread(f"Async-{name}")
print(f"线程 {name} 执行结束,结果: {result}")

# 主函数
def main():

start = time.time()
# 创建并启动线程
threads = []
for i in range(16):
thread = threading.Thread(target=thread_function, args=(f"Thread-{i+1}",))
threads.append(thread)
thread.start()

# 等待所有线程完成
for thread in threads:
thread.join()


print(f"所有任务执行完毕, 耗时: {time.time() - start} s" )


if __name__ == "__main__":
main()
  • 多进程
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    import threading
    import asyncio
    import time
    import multiprocessing
    from typing import List


    async def async_range(n):
    for i in range(n):
    yield i


    # 异步任务
    async def async_task(name):
    for i in range(20):
    print(f"异步任务 {name} 开始执行")
    async for i in async_range(1000_0000):
    pass
    print(f"异步任务 {name} 执行结束")
    return f"结果 {name}"


    # 在进程中运行异步任务
    def run_async_in_thread(name):
    # 创建一个新的事件循环
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    # 运行异步任务
    result = loop.run_until_complete(async_task(name))

    # 关闭事件循环
    loop.close()

    return result


    # 线程函数
    def thread_function(name):
    print(f"进程 {name} 开始执行")
    result = run_async_in_thread(f"Async-{name}")
    print(f"进程 {name} 执行结束,结果: {result}")


    # 主函数
    def main():

    start = time.time()
    # 创建并启动进程
    processes: List[multiprocessing.Process] = []
    for i in range(16):
    process = multiprocessing.Process(
    target=thread_function, args=(f"Process-{i+1}",)
    )
    processes.append(process)
    process.start()

    # 等待所有进程完成
    for process in processes:
    process.join()

    print(f"所有任务执行完毕, 耗时: {time.time() - start} s")


    if __name__ == "__main__":
    main()

运行时间对比

  • 使用 No-GIL python3.13 耗时66s
  • 使用 GIL python3.13 耗时375s
  • 使用带GIL的多进程65s

有了multiprocessing,为什么还要No-GIL ?

因为multiprocessing是多进程, 每个进程都有自己的内存空间, 进程间通信成本较高

  • 进程间通信手段: Queue, Pipe, Semaphore, Socket, File
  • 线程间同步: Lock, RLock, Condition, Event, Queue, Barrier

NO-GIL的最大优势:

  • 同一程序空间,线程间通信简单

[附] 多进程和多线程的区别:

  • 多进程: 每个进程有自己的内存空间

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    from multiprocessing import Process

    # 定义一个全局变量
    counter = 0

    def increment():
    global counter
    for _ in range(1000000):
    counter += 1

    if __name__ == "__main__":
    # 创建两个进程
    p1 = Process(target=increment)
    p2 = Process(target=increment)

    # 启动进程
    p1.start()
    p2.start()

    # 等待进程完成
    p1.join()
    p2.join()

    # 打印最终的全局变量值
    print(f"Final counter value: {counter}")

    运行结果:

    1
    2
    3
    4
    $ python3.13 test_process.py
    counter: 1000000
    counter: 1000000
    Final counter value: 0

    因为主进程中的 counter没有改过, 所以最终的结果是0

  • 多线程: 共享内存空间

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # from multiprocessing import Process
    from threading import Thread

    # 定义一个全局变量
    counter = 0

    def increment():
    global counter
    for _ in range(1000000):
    counter += 1

    if __name__ == "__main__":
    # 创建两个进程
    p1 = Thread(target=increment)
    p2 = Thread(target=increment)

    # 启动进程
    p1.start()
    p2.start()

    # 等待进程完成
    p1.join()
    p2.join()

    # 打印最终的全局变量值
    print(f"Final counter value: {counter}")
    • 使用 GIL版本运行结果:

      1
      2
      $ python3.13 -Xgil=1 test_thread.py
      Final counter value: 2000000
    • 使用 No-GIL版本运行结果:

      1
      2
      3
      4
      5
      6
      7
      8
      $ python3.13 -Xgil=0 test_thread.py
      Final counter value: 1139283
      $ python3.13 -Xgil=0 test_thread.py
      Final counter value: 1170427
      $ python3.13 -Xgil=0 test_thread.py
      Final counter value: 1415999
      $ python3.13 -Xgil=0 test_thread.py
      Final counter value: 1205918
      • 因为没有GIL的限制, 且没有加锁, 所以多线程的结果是不确定的
    • 对counter加锁

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    from threading import Thread, Lock

    # 定义一个全局变量
    counter = 0

    lock = Lock()

    def increment():
    global counter
    for _ in range(1000000):
    lock.acquire() # 获取锁
    counter += 1
    lock.release() # 释放锁

    if __name__ == "__main__":
    # 创建两个进程
    p1 = Thread(target=increment)
    p2 = Thread(target=increment)

    # 启动进程
    p1.start()
    p2.start()

    # 等待进程完成
    p1.join()
    p2.join()

    # 打印最终的全局变量值
    print(f"Final counter value: {counter}")

    使用无GIL python运行结果:

    1
    2
    $ python3.13 -Xgil=0 test_thread.py
    Final counter value: 2000000

Raydium做市资金量计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from math import sqrt


def calc_market(market_cap_in_usd: float, sol_price_in_usd: float):

# k = x * y 量纲 t*s , s 为 sol , t 为 token
k = 79 * (10_0000_0000 - 7_9310_0000)

P = 0 # 量纲 s/t
if True:
# 量纲 u/s , u为usd
target_sol_price = sol_price_in_usd

# 量纲 u/t , u为usd
target_token_price = market_cap_in_usd / 10_0000_0000

# p = (u/t) / (u/s) , 目标量纲为 s/t
P = target_token_price / target_sol_price
# print(p)

# y^2 = k / p , 量纲为 ts / (s/t) = t^2 , 因此 y的量纲为 t
Y = sqrt(k / P)

# x = p * y , 量纲为 (s/t) * t = s , 因此 x 的量纲为 s
X = P * Y

return X, Y


target_market_cap_in_usd_lists = [1_0000_0000 * i for i in range(1, 11)]
sol_price_in_usd = 230

for target_market_cap in target_market_cap_in_usd_lists:
ret = calc_market(target_market_cap, sol_price_in_usd)
print(
f"拉盘到{target_market_cap:0.0f}美金市值, 所需资金数量: {ret[0]:0.0f} 枚SOL , 约合 {ret[0] * sol_price_in_usd : 0.0f} USDT"
)

计算结果:

1
2
3
4
5
6
7
8
9
10
拉盘到100000000美金市值,  所需资金数量: 2666 枚SOL , 约合  613137 USDT
拉盘到200000000美金市值, 所需资金数量: 3770 枚SOL , 约合 867107 USDT
拉盘到300000000美金市值, 所需资金数量: 4617 枚SOL , 约合 1061985 USDT
拉盘到400000000美金市值, 所需资金数量: 5332 枚SOL , 约合 1226275 USDT
拉盘到500000000美金市值, 所需资金数量: 5961 枚SOL , 约合 1371017 USDT
拉盘到600000000美金市值, 所需资金数量: 6530 枚SOL , 约合 1501873 USDT
拉盘到700000000美金市值, 所需资金数量: 7053 枚SOL , 约合 1622209 USDT
拉盘到800000000美金市值, 所需资金数量: 7540 枚SOL , 约合 1734214 USDT
拉盘到900000000美金市值, 所需资金数量: 7997 枚SOL , 约合 1839412 USDT
拉盘到1000000000美金市值, 所需资金数量: 8430 枚SOL , 约合 1938910 USDT
  • Copyrights © 2021-2025 youngqqcn

请我喝杯咖啡吧~