Bilibili cache transcoding | FFmpeg converts m4s files to mp4 | PHP automatically batch transcodes Bilibili videos

window download and install FFmpeg

Configure FFmpeg environment variables

The FFmpeg downloaded above is green software. Just download and unzip it to your common software installation directory, then enter the bin and copy the system environment variables under the full path configuration.

Insert image description here
Insert image description here

Terminal command processing

Insert image description here

# 常规命令
ffmpeg -i video.m4s -i audio.m4s -codec copy video.mp4

# 屏蔽输出日志
ffmpeg -loglevel quiet -i video.m4s -i audio.m4s -codec copy video.mp4

Insert image description here

Call FFmpeg using PHP

  • https://github.com/PHP-FFMpeg/PHP-FFMpeg/
<?php

// require 'vendor/autoload.php';
// $ffmpeg = FFMpeg\FFMpeg::create();
// $oldAudio = $ffmpeg->open('./assets/32.amr');
// $newAudio = new FFMpeg\Format\Audio\Mp3();
// $newAudio->setAudioKiloBitrate(8); // 设置音频比特
// $oldAudio->save($newAudio, './assets/32.mp3');

// shell_exec("ffmpeg -i 32.amr b.mp3"); // cmd可执行

/* http请求可执行 */
// $file = './src/32.amr';
// $outFile = './src/b.mp3';
// $handle = popen("ffmpeg -i $file $outFile", 'w'); 
// pclose($handle);


// $filePath = './src/32.amr';
// $filePath_mp =  './src/b.mp3';
// echo "ffmpeg -i $filePath $filePath_mp";
// $handle = popen("ffmpeg -i $filePath  $filePath_mp", 'w');
// pclose($handle);



shell_exec("ffmpeg -i video.m4s -i audio.m4s -codec copy video.mp4"); // cmd可执行
  • batch processing program
<?php
date_default_timezone_set("PRC");
header("Content-type: text/html; charset=utf-8"); 
set_time_limit(0);

// 遍历获取文件
function getDirFile($path = null, $deep = true) {
    
    
    if (empty($path)) {
    
    
        return [];
    }
    $files = scandir($path);
    $fileItem = [];
    foreach($files as $v) {
    
    
        $newPath = $path .DIRECTORY_SEPARATOR.$v;
        if($deep && is_dir($newPath) && $v != '.' && $v != '..') {
    
    
          if (is_numeric($deep)) {
    
    
            $deep--;
          }
            $fileItem = array_merge($fileItem, getDirFile($newPath, $deep));
        }else if(is_file($newPath)){
    
    
            $fileItem[] = $newPath;
        }
    }
    return $fileItem;
}

// 遍历获取文件夹
function getDir($path = null, $deep = true) {
    
    
    if (empty($path)) {
    
    
        return [];
    }
    $files = scandir($path);
    $dirList = [];
    foreach($files as $v) {
    
    
        $newPath = $path .DIRECTORY_SEPARATOR.$v;
        if (is_dir($newPath) && $v != '.' && $v != '..') {
    
    
          $dirList[] = $newPath;
          if ($deep) {
    
    
            if (is_numeric($deep)) {
    
    
            $deep--;
          }
          $dirList = array_merge($dirList, getDir($newPath, $deep));
          }
        }
    }
    return $dirList;
}

//判断文件夹是否存在,没有则新建。
if (!function_exists('mkdirs')) {
    
    
    function mkdirs($dir, $mode = 0777)
    {
    
    
        if (is_dir($dir) || @mkdir($dir, $mode)) {
    
    
            return true;
        }
        if (!mkdirs(dirname($dir), $mode)) {
    
    
            return false;
        }
        return @mkdir($dir, $mode);
    }
}

/**
 * 操作文件夹
 * addtime 2020年7月17日
 * @param [type] $dirname 文件夹路径
 * @param boolean $self  是否删除文件夹本身[true是 false否] 具体看需求
 * @return void
 */
function do_rmdir($dirname, $self = false) 
{
    
    
    # 检查文件或目录是否存在
    if (!file_exists($dirname)) {
    
    
      return false;
    }
    # 是文件进行删除
    if (is_file($dirname) || is_link($dirname)) {
    
    
      return unlink($dirname);
    }
    # 开始读取目录
    $dir = dir($dirname);
    if ($dir) {
    
    
      while (false !== $entry = $dir->read()) {
    
    
        if ($entry == '.' || $entry == '..') {
    
    
          continue;
        }
        # 进行文件删除
        do_rmdir($dirname . '/' . $entry);
      }
    }
    # 关闭目录
    $dir->close();
    # 是否删除本身文件夹
    $self && rmdir($dirname);
    # 成功返回
    return ['code' => 200];
}

$inputParams = getopt('d:s:'); // 接收-d参数
if (empty($inputParams['d']) || !file_exists($inputParams['d'])) {
    
    
  die(PHP_EOL.'请输入正确的B站视频文件目录');
}
// $isNo = empty($inputParams['s'])?false: true;
// print_r($inputParams);
// die();
$inputDir = $inputParams['d'];
$outputDir = dirname(__FILE__).DIRECTORY_SEPARATOR. $inputDir.'Mp4';
do_rmdir($outputDir, true);
mkdirs($outputDir);
$isDebug = false;


$list = getDir($inputDir, false);
if (empty($list)) {
    
    
  die(PHP_EOL.'空文件夹。。。');
}
$i = 0;
foreach ($list as $key => $item) {
    
    
  $entryJson = $item. DIRECTORY_SEPARATOR . 'entry.json';
  $audio = $item. DIRECTORY_SEPARATOR . '80' . DIRECTORY_SEPARATOR . 'audio.m4s';
  $video = $item. DIRECTORY_SEPARATOR . '80' . DIRECTORY_SEPARATOR . 'video.m4s';
  if (file_exists($entryJson) && file_exists($audio) && file_exists($video)) {
    
    
    $entryJsonText = file_get_contents($item. DIRECTORY_SEPARATOR . 'entry.json');
    if (!empty($entryJsonText)) {
    
    
      $entryJsonText = json_decode($entryJsonText, true);
      $fileName = $entryJsonText['page_data']['part'];
      // $fileName = explode($separator, $fileName, 2);
      // $fileName[0] = str_pad($fileName[0], 3, '0', STR_PAD_LEFT );
      // $fileName = implode('.', $fileName);
      
      // 替换中文括号
      $fileName = str_replace('(', '(', $fileName);
      $fileName = str_replace(')', ')', $fileName);
      // 替换文件名不能含有的符号? \ / : | * "
       
      $fileName = str_replace('\\', '_{_', $fileName);
      $fileName = str_replace('/', '_}_', $fileName);
      $fileName = str_replace(':', ':', $fileName);
      $fileName = str_replace('*', '_ALL_', $fileName);
      $fileName = str_replace('<', '《', $fileName);
      $fileName = str_replace('>', '》', $fileName);
      $fileName = str_replace('|', '_OR_', $fileName);

      // 是否开启编号
      $No = str_pad($entryJsonText['page_data']['page'], 3, '0', STR_PAD_LEFT );

      $cmdFileName = $outputDir . DIRECTORY_SEPARATOR . $No . '.mp4';
      $fileName = $outputDir . DIRECTORY_SEPARATOR . $No. '.' . $fileName . '.mp4';
      $cmd = "ffmpeg ".($isDebug? "": "-loglevel quiet")." -i {
      
      $audio} -i {
      
      $video} -codec copy {
      
      $cmdFileName}";
      shell_exec($cmd); // cmd可执行
      // 重命名
      rename($cmdFileName, $fileName);
      print_r([
        'index' => $i++,
        'path' => $item,
        'fileName' => $fileName,
        'cmd'   => $cmd,
      ]);
    }
  } 
}
echo PHP_EOL;
print_r(array(
  '总计文件' => count($list),
  '完成文件' => $i,
));
  • run script
php index.php -d 目录名

Insert image description here

reference

Guess you like

Origin blog.csdn.net/qq_35606400/article/details/132017381