Node.js 视频上传获取解码器

Node.js video upload get Codec

我的用户可以上传视频到我的网站。然而,出现了一些视频文件的编解码器不受浏览器支持的问题 (YUV)

所以我想研究如何查看编解码器。

目前我正在使用 multer 处理我的文件:

app.use(multer({
    dest: './uploads/',
    rename: function (fieldname, filename) {
        return filename + Date.now();
    },

    onFileUploadStart: function (file) {
        var i = 0;
    },
    onFileUploadComplete: function (file) {
        //Redirects request to path
        var i = 0;
    }
}));

设置断点并检查文件我得到的唯一信息:

所以我的问题是:是否可以查看上传文件的编解码器?

首先,值得一提的是,YUV 是一种颜色 space 而不是编解码器 - 类似于可能更容易理解的 RGB(红绿蓝)颜色 space。它是表示图像中像素的亮度和颜色的一种方式。许多编解码器使用 YUV 颜色 space,因为它促进了编解码器需要执行的计算类型,并减少了冗余。

如果您确实想找到特定视频文件正在使用的编解码器,以及相当多的其他信息,那么请进行基本分析以查看您上传的视频的类型和格式是什么相当艰巨的任务,因为格式太多了。

我认为最简单的方法是在可以的情况下利用 ffprobe 功能:

有些模块提供了 ffprobe 的包装器,因此您可以从节点使用它 - 例如:

使用这种方法可以非常简单地生成视频文件信息,然后您可以解析这些信息以获取编解码器。上面的用法示例 link(在撰写本文时正确):

var probe = require('node-ffprobe');

var track = '/path/to/media/file.mp3';

probe(track, function(err, probeData) {
    console.log(probeData);
});

以及 ffprobe 为无处不在的 BigBuckBunny 视频示例生成的输出类型示例:

ffprobe version 2.6.1 Copyright (c) 2007-2015 the FFmpeg developers
  built with llvm-gcc 4.2.1 (LLVM build 2336.11.00)
  configuration: --prefix=/Volumes/Ramdisk/sw --enable-gpl --enable-pthreads --enable-version3 --enable-libspeex --enable-libvpx --disable-decoder=libvpx --enable-libmp3lame --enable-libtheora --enable-libvorbis --enable-libx264 --enable-avfilter --enable-libopencore_amrwb --enable-libopencore_amrnb --enable-filters --enable-libgsm --enable-libvidstab --enable-libx265 --disable-doc --arch=x86_64 --enable-runtime-cpudetect
  libavutil      54. 20.100 / 54. 20.100
  libavcodec     56. 26.100 / 56. 26.100
  libavformat    56. 25.101 / 56. 25.101
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 11.102 /  5. 11.102
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  1.100 /  1.  1.100
  libpostproc    53.  3.100 / 53.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '.../vid_bigbuckbunny.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 1
    compatible_brands: mp42avc1
    creation_time   : 2010-02-09 01:55:39
  Duration: 00:01:00.10, start: 0.000000, bitrate: 733 kb/s
    Stream #0:0(eng): Audio: aac (LC) (mp4a / 0x6134706D), 22050 Hz, stereo, fltp, 65 kb/s (default)
    Metadata:
      creation_time   : 2010-02-09 01:55:39
      handler_name    : Apple Sound Media Handler
    Stream #0:1(eng): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, smpte170m/smpte170m/bt709), 640x360, 612 kb/s, 23.96 fps, 24 tbr, 600 tbn, 1200 tbc (default)
    Metadata:
      creation_time   : 2010-02-09 01:55:39
      handler_name    : Apple Video Media Handler
    Stream #0:2(eng): Data: none (rtp  / 0x20707472), 45 kb/s
    Metadata:
      creation_time   : 2010-02-09 01:55:39
      handler_name    : hint media handler
    Stream #0:3(eng): Data: none (rtp  / 0x20707472), 5 kb/s
    Metadata:
      creation_time   : 2010-02-09 01:55:39
      handler_name    : hint media handler

ffprobe 无法识别的任何内容大多不是视频,或者即使是视频也无法在常规浏览器中播放。

值得检查 ffmpeg/ffprobe 许可,以确保它也满足您的需求。

您可以使用以下代码检测编解码器。我有类似的问题。 iphone 中生成的一些视频采用 hevc 编解码器。我可以使用 ffprobe 获取视频的编解码器。因为我之前安装了 ffmpeg,所以我只是用 @ffprobe-installer/ffprobe.

安装了 ffprobe 二进制文件
const ffmpeg= require('fluent-ffmpeg');
const ffprobeInstaller = require('@ffprobe-installer/ffprobe');
ffmpeg.setFfprobePath(ffprobeInstaller.path);

/**Get codec of the video file.
 * 
 * @param {*} filePath 
 * @returns codec of the file
 */
const getCodec=(filePath)=>{
    return new Promise((resolve,reject)=>{
        try {
            
            ffmpeg.ffprobe(filePath,function(err, probeData) {
                //console.log("probeData for ",filePath,probeData,err);
                if(err)return reject(err);
                else{
                    return resolve(probeData.streams[0].codec_name);
                }
            });            
        } catch (error) {
            return reject(error);
        }        
    });
    
}
exports.getCodec=getCodec;

不仅如此,您还可以使用以下代码将编解码器更改为可播放的格式。这使用了ffmpeg。只需安装 npm fluent-ffmpeg:

ffmpeg.setFfmpegPath( require('@ffmpeg-installer/ffmpeg'));
/**Convert video to regular mp4(h.264) codec
 * 
 * @param {*} source 
 * @param {*} destination 
 * @returns 
 */
const convertVideo=(source,destination)=>{
    return new Promise((resolve,reject)=>{
        try {
            ffmpeg(source).videoCodec('libx264').output(destination).on('end', function() {                    
                console.log('conversion ended');
                return resolve(destination);
            }).on('error', function(err){
                console.log('error: ', err.code, err.msg);
                return reject(err);                
            }).run();
            
        } catch (error) {
            return reject(error);
        }        
    });    
}
exports.convertVideo=convertVideo;