视频相关处理

获取视频的分辨率

1
2
3
4
5
ffprobe -v error \
  -select_streams v:0 \
  -show_entries stream=width,height \
  -of csv=p=0 \
  2-PNA.mp4

ffprobe是通过homebrew安装的,它会输出视频的分辨率。

将视频转化成音频

yt-dlp:视频下载

  • 它是通过python的pip工具进行安装。官网:https://github.com/yt-dlp/yt-dlp,关于options可以看介绍,以及在python中如何配置参数,可以看:https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/options.py
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    import yt_dlp
    url = "***"# 指定要下载的url,如果是一个合集的url,在下载的时候没有指定某一集,会下载所有的集数
    ydl_opts = {
        'playlist_items': '14',#指定下载某一集,也可以指定下载范围,只有url为合集的时候才起作用
        'cookiefile': 'cookies.txt',#指定cookie文件,一般google浏览器通过安装get cookies.txt插件,方便下载会员视频
        'outtmpl': '要下载的父文件夹/%(playlist_index)02d - %(title)s.%(ext)s',#指定下载的路径和名字
    
        'format': 'bestvideo+bestaudio/best',#指定下载的视频分辨率和音频的采样率,这里如果音频和视频分开的,可以只下载音频或视频
    
        'concurrent_fragment_downloads': 8,#指定单集下载的线程个数
    
    
        'ignoreerrors': True,#是否忽略下载失败后继续下载
        'merge_output_format': 'mp4',#指定音频和视频合并后的视频类型
    }
    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
        ydl.download([url])
    
  • yt-dlp -F url:可以查看资源支持哪些格式,有些视频不支持视频和音频分开。

水印处理(Python+OpenCV)

  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
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import cv2
import numpy as np
from pathlib import Path

def get_watermark_coordinates(video_file, frame_number=0):
    """
    交互式获取水印坐标
    
    参数:
        video_file: 视频文件路径
        frame_number: 要分析的帧号(默认第一帧)
    
    返回:
        (x, y, width, height) 或 None
    """
    cap = cv2.VideoCapture(video_file)
    
    if not cap.isOpened():
        print(f"❌ 无法打开视频: {video_file}")
        return None
    
    # 跳转到指定帧
    cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
    ret, frame = cap.read()
    cap.release()
    
    if not ret:
        print("❌ 无法读取帧")
        return None
    
    # 显示视频信息
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    fps = cap.get(cv2.CAP_PROP_FPS)
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    
    print(f"视频信息: {width}x{height}, {total_frames}帧, {fps:.2f}fps")
    print(f"当前帧: {frame_number}/{total_frames}")
    print("\n操作说明:")
    print("1. 在窗口中拖拽鼠标选择水印区域")
    print("2. 按 Enter 确认")
    print("3. 按 ESC 取消")
    
    # 选择 ROI(Region of Interest)
    roi = cv2.selectROI('选择水印区域 (按 Enter 确认, ESC 取消)', frame, False)
    cv2.destroyAllWindows()
    
    if roi[2] > 0 and roi[3] > 0:
        x, y, w, h = roi
        print(f"\n✅ 水印坐标:")
        print(f"   x (左上角X): {x}")
        print(f"   y (左上角Y): {y}")
        print(f"   width (宽度): {w}")
        print(f"   height (高度): {h}")
        print(f"\nFFmpeg 命令:")
        print(f'   ffmpeg -i "{video_file}" -vf "delogo=x={x}:y={y}:w={w}:h={h}" output.mp4')
        
        return (x, y, w, h)
    else:
        print("❌ 未选择区域")
        return None


def get_multiple_watermarks(video_file, frame_number=0):
    """
    选择多个水印区域
    """
    cap = cv2.VideoCapture(video_file)
    cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
    ret, frame = cap.read()
    cap.release()
    
    if not ret:
        return []
    
    watermarks = []
    frame_copy = frame.copy()
    
    print("选择水印区域(可以多次选择)")
    print("按 Enter 确认当前选择,按 ESC 完成所有选择")
    
    while True:
        roi = cv2.selectROI('选择水印区域 (Enter确认, ESC完成)', frame_copy, False)
        
        if roi[2] > 0 and roi[3] > 0:
            x, y, w, h = roi
            watermarks.append((x, y, w, h))
            
            # 在图像上标记已选择的区域
            cv2.rectangle(frame_copy, (x, y), (x+w, y+h), (0, 255, 0), 2)
            cv2.putText(frame_copy, f"#{len(watermarks)}", (x, y-10), 
                    cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
            
            print(f"✅ 已选择水印 #{len(watermarks)}: x={x}, y={y}, w={w}, h={h}")
        else:
            break
    
    cv2.destroyAllWindows()
    
    return watermarks


# 使用示例
if __name__ == "__main__":
    video_file = "input.mp4"
    
    # 获取单个水印坐标
    coords = get_watermark_coordinates(video_file, frame_number=0)
    
    # 获取多个水印坐标
    # watermarks = get_multiple_watermarks(video_file)
    # for i, (x, y, w, h) in enumerate(watermarks, 1):
    #     print(f"水印 {i}: x={x}, y={y}, w={w}, h={h}")

执行上面的python后,接着会弹出交互式界面,此时选中水印,然后就会输出坐标信息:

1
2
3
4
5
6
7
8
 水印坐标:
x (左上角X): 1115
y (左上角Y): 45
width (宽度): 333
height (高度): 77

FFmpeg 命令:
ffmpeg -i "input.mp4" -vf "delogo=x=1115:y=45:w=333:h=77" output.mp4

接着我们执行该ffmpeg命令就行,会输出不带水印的视频。

视频提取原声/BGM/去掉人声等

首先需要安装demucs的虚拟环境,安装虚拟环境需要用到pyenv,首先安装pyenv:

1
brew install pyenv

然后录配置pyenv的path路径,在zshrc或bash中配置:

1
2
3
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

然后同步下配置:source ~/.zshrc。 然后安装虚拟环境的python版本:

1
pyenv install 3.10.14

接着需要安装pyenv-virtualenv用于指定虚拟环境的名字:

1
brew install pyenv-virtualenv

然后给pyenv-virtualenv添加上环境变量:

1
eval "$(pyenv virtualenv-init -)"

接着指定虚拟环境的名字和激活虚拟环境:

1
2
pyenv virtualenv 3.10.14 demucs-env\
pyenv activate demucs-env

此时就激活了虚拟环境demucs-env,此时在命令行中能看到虚拟环境的名字,如果要断开虚拟环境使用:pyenv deactivate demucs-env。 接着要装相关的依赖组件,分别是:

1
2
3
4
pip install numpy==1.26.4
pip install torch==2.2.2 torchaudio==2.2.2
pip install demucs
pip install torchcodec

此时还需要ffmpeg,这个可以通过brew install ffmpeg进行安装。所有安装完成后,最后同步下命令:hash -r。这样python的虚拟环境就安装完成了。 此时可以通过python3 video_audio_example.py 2去执行各种功能。功能都在两个python事例文件python功能文件中。

常用demucs的命令:

1
demucs --two-stems=vocals 音频路径

此时会分离出音频的人声和bgm。

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计