卢春龙
2026-08-17 f525b6c3cc105bd1a997d893937689bebcc9570d
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
/**********************************************************************
 * 视频相关帮助函数
 * Created By lucl@xiaopeng.com
 * Created on Mon Nov 20 2023
 **********************************************************************/
 
import { removeQs } from "./tools";
 
/**
 * 判断是否是视频链接
 * @param url
 */
export function checkIsVideoUrl(url: string): boolean {
  if (!url) return false;
  try {
    const arr = removeQs(url).split('.');
    const ext = arr[arr.length - 1];
    const exts = [
      'mp4',
      'avi',
      'rmvb',
      'rm',
      'asf',
      'divx',
      'mpg',
      'mpeg',
      'mpe',
      'wmv',
      'mkv',
      'vob',
      'mov',
      '3gp',
      'ogg',
      'dat',
      'ogm',
      'flv',
      'f4v'
    ];
    return exts.includes(ext);
  } catch (error) {
    console.error('checkIsVideoUrl error-->:', url, error);
    return false;
  }
}
 
/**
 * 格式化视频链接
 */
export function formatVideoUrl(url: string) {
  if (!checkIsVideoUrl(url)) return url;
  // vd.xiaopeng.com 相比 s.xiaopeng.com 在运维层面做了更多视频优化
  url = url.replace(
    'https://s.xiaopeng.com/bbs/uploaded/',
    'https://vd.xiaopeng.com/bbs/uploaded/'
  );
 
  return url;
}
 
/**
 * 获取视频名称。
 * 用途:formatVideoUrl 以后的 url 和原 url 的域名已经不同,因此只比较视频名称
 */
export function getVideoName(url: string) {
  if (!url) return '';
  url = removeQs(url);
  const arr = url.split('/');
  return arr[arr.length - 1];
}
 
interface GetVideoCoverFromUrlOptions {
  time: number; // 指定截图时间,单位为 ms。如果需要截取视频封面,则t设置为0。
  width: number; // 指定截图宽度,如果指定为0,则根据截图高度与源视频高度比例自动计算。
  height: number; // 指定截图高度,如果指定为0,则根据截图宽度与源视频宽度比例自动计算;如果w和h都为0,则输出为原视频宽高。
  fastMode: boolean; // 是否开启 fast 模式,截取该时间点之前的最近的一个关键帧。
  format: 'jpg' | 'png'; // 指定输出图片的格式。
  autoRotate: 'auto' | 'h' | 'w' | ''; // 指定是否根据视频信息自动旋转图片。
}
 
/**
 * 视频截帧
 */
export function getVideoSnapshot(
  url: string,
  options: GetVideoCoverFromUrlOptions = {
    time: 0,
    width: 0,
    height: 0,
    fastMode: true,
    format: 'jpg',
    autoRotate: ''
  }
) {
  if (!checkIsVideoUrl(url)) return '';
  const { time, width, height, fastMode, format, autoRotate } = options;
  const commands: string[] = [];
  commands.push(`t_${time}`);
  commands.push(`f_${format}`);
  commands.push(`w_${width}`);
  commands.push(`h_${height}`);
  if (fastMode) {
    commands.push('m_fast');
  }
  if (autoRotate) {
    commands.push(`ar_${autoRotate}`);
  }
  const query = `?x-oss-process=video/snapshot,${commands.join(',')}`;
  return `${formatVideoUrl(url)}${query}`;
}