找回密码
 立即注册
首页 业界区 科技 视频流的传播

视频流的传播

予捻 前天 13:13
  这个项目是我大三做的,和我的very very nice的好哥们Pz做的。其中他负责了idea、Sample Montior的C++底层的部分和最后测试,我负责了流式传输部分
  现在我们来看一看这份代码
  1. import threading
  2. import ffmpeg
  3. from screeninfo import get_monitors
  4. monitors = get_monitors()
  5. secondary_monitor = monitors[0]
  6. screen_x = secondary_monitor.width
  7. screen_y = secondary_monitor.height
  8. # 设置UDP传输地址和端口
  9. udp_url = 'udp://127.0.0.1:12345'
  10. output_format = 'mp4'
  11. output_file = f'output.{output_format}'
  12. input_params = {
  13.     'f': 'gdigrab',  # 屏幕录像并推流
  14.     'framerate': 30,  # 帧率
  15.     'offset_x': monitors[0].x,
  16.     'offset_y': monitors[0].y,
  17.     's': f'{screen_x}x{screen_y}',
  18.     'probesize': '50M',  # 输入流格式时应该读取的数据量
  19. }
  20. output_params = {
  21.     'f': 'mpegts',  # 延迟优化
  22.     'vcodec': 'libx264',
  23.     'pix_fmt': 'yuv420p',
  24.     'vf': 'fps=30',
  25.     's': '1920x1080',  # 根据需要调整分辨率
  26.     'pkt_size': 1316
  27. }
  28. input_stream = ffmpeg.input('desktop', **input_params)
  29. output_stream1 = ffmpeg.output(input_stream, output_file, **output_params)
  30. output_stream2 = ffmpeg.output(input_stream, udp_url, **output_params)
  31. # 定时器回调函数
  32. def stop_recording():
  33.     process.communicate()
  34.     print("录制结束")
  35. # 设置录制时间(以秒为单位)
  36. record_time = 10
  37. timer = threading.Timer(record_time, stop_recording)
  38. timer.start()
  39. # 开始录制
  40. key1 = input("按 'q' 开始录制...")
  41. if key1 == "q":
  42.     process = ffmpeg.run_async(output_stream2)
  43.     print("开始录制...")
  44. # 结束录制
  45. key2 = input("按 'q' 停止录制...")
  46. if key2 == "q":
  47.     timer.cancel()  # 取消定时器
  48.     process.terminate()  # 终止录制进程
  49.     print("录制终止")
复制代码
  那个时候,我对于视频传输一无所知,所以在经过了大量的学习,和询问chatGpt后,才有了一份这样的代码,我想先说说她的缺点、优点,再仔细的讲解她
  (用女字旁更多的是对代码有怀念,就像船员称呼自己的舰船一样)
关于代码
1.优点:
    简单、好懂
    是我自己写的
2.缺点:
    延迟高,不可用
    不可以传声音
3.讲解:
    讲解主要分为两个部分——输入字典的解析+输出字典的解析,因为其他的确实没啥好讲的(所以好懂,太初学者了)
  (1)输入字典
      f: 'gdigrab':这是指定输入格式为 gdigrab(Graphics Device Interface Grab),它是 Windows 下 FFmpeg 用来捕获屏幕的一个格式。它可以直接录制屏幕的内容。
      framerate: 30:设置录制的帧率为 30 帧每秒,这意味着每秒录制 30 帧画面。
      offset_x 和 offset_y:这两个参数定义了屏幕截图的起始位置(左上角的坐标);monitors[0].x 和 monitors[0].y 是显示器的坐标信息,并从某个特定的屏幕区域开始录制。
      s: f'{screen_x}x{screen_y}':这里设置了录制区域的分辨率。screen_x 和 screen_y 表示需要录制的屏幕区域的宽度和高度。
      probesize: '50M':这是 FFmpeg 用来检测输入流格式的参数。probesize 指定了 FFmpeg 在读取数据流之前,应该读取的最大数据量。
  (2)输出字典
      f: 'mpegts':指定输出格式为 mpegts(MPEG Transport Stream),通常用于流媒体传输,尤其是在网络推流时有优化延迟的效果。
      vcodec: 'libx264':指定视频编码使用 libx264,这是一种常用的 H.264 编码器,广泛支持并且提供了高压缩效率。
      pix_fmt: 'yuv420p':这是输出视频的像素格式。yuv420p 是一种常见的格式,特别适用于 H.264 编码。
      vf: 'fps=30':这是视频过滤器选项,指定了输出视频的帧率是 30 帧每秒。这保证了输出流的帧率和输入流一致。
      s: '1920x1080':输出视频的分辨率,这里设置为 1920x1080,适合高清格式。如果你希望调整输出分辨率,可以根据需求修改。
      pkt_size: 1316:指定每个网络包的大小。这个值是根据网络带宽、延迟等因素优化的,以减少传输中的延迟。1316 字节是一个常用的包大小,它有助于提高实时推流的性能。
问题
  1.什么是gdigrab?
  2.为什么FFmpeg 在读取数据流之前,要读取的最大数据量?
  3.什么是mpegts?
  4.libx264前的libx是什么?
  5.yuv420p前的yuv是什么?
回答
  1.gdigrab 是 FFmpeg 在 Windows 系统下提供的一种视频输入格式,用于捕获屏幕上的图像或特定应用窗口的内容。
   (1)GDI (Graphics Device Interface)是 Windows 操作系统中的一个重要图形接口,它允许应用程序与显示器或打印机交互。通过 GDI,程序可以绘制图形、捕获屏幕内容等。
   (2)其命令行为ffmpeg -f gdigrab -framerate 30 -i desktop output.mp4,抓取名为desktop屏幕,每秒30帧,输出output.mp4文件
  2.为了让 FFmpeg 能够有效地解析输入流的格式,并准确地了解数据流的结构
   (1)流格式探测:FFmpeg 需要一定的样本数据来探测和识别输入流的格式、编码信息、分辨率、音频或视频轨道等;通过读取一定量的数据,FFmpeg 可以判断编码类型、帧率、分辨率等信息。
   (2)避免数据流阻塞:如果流源非常大或存在未知的封装格式,FFmpeg 可能无法立即解析所有信息。通过设置 probesize 限制 FFmpeg 读取的数据量,防止解析过程中过度占用系统资源或阻塞过长时间。
   (3)在完成上面两项任务后,还需要解析输入流,其中 probesize 大小设置一般为5MB或50MB
  3.mpegts(MPEG Transport Stream)是一种广泛用于音视频流传输的容器格式,通常用于广播和网络流媒体传输。
   (1)容错性强、适用于实时传输、小的数据包、时间戳和同步
   (2)用于数字电视广播、视频流媒体
   (3)结构:头部+负载(我将信息介绍放在最下面)
  4.libx264 中 libx 是 x264 编码器的一个 软件库(library),用于实现 H.264 视频编码标准。
  5.yuv420p 中 yuv 是 图像存储格式,颜色存储空间;只有 y 时图片是黑白的,u 表示蓝色与亮度的差异, v 表示红色与亮度的差异。
头部与负载

  • 头部:包含了用于同步、标识流类型和控制流的基本信息,包括一个 4 字节的标识符,通常包括:




    • Sync byte:同步字节,确保数据包的起始位置



    • PID标识(Packet Identifier):标识当前数据包所属的流或数据类型



    • PES标识(Packetized Elementary Stream):指示包内是否包含原始的音视频数据



    • 时间戳:用于流的同步和错误恢复


  • 负载:包含了实际的音频、视频或其他数据,是数据包的主要部分。




    • 压缩的音视频数据



    • 字幕信息



    • 数据流的控制信息

那个时候好像,我的前女友也在。。。唉,仅仅纪念一下美好的项目生涯和恋爱生活~!

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册