哔哩哔哩缓存转码|FFmpeg将m4s文件转为mp4|PHP自动批量转码B站视频

window下载安装FFmpeg

配置FFmpeg环境变量

上面下载的FFmpeg是绿色软件,下载解压到你的常用软件安装目录即可,然后进入bin复制全路径配置下系统环境变量即可


终端命令处理

bash 复制代码
ffmpeg -i video.m4s -i audio.m4s -codec copy video.mp4

使用PHP调用FFmpeg

php 复制代码
<?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可执行
  • 批量处理程序
php 复制代码
<?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:'); // 接收-d参数
if (empty($inputParams['d']) || !file_exists($inputParams['d'])) {
	die(PHP_EOL.'请输入正确的B站视频文件目录');
}
$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.'空文件夹。。。');
}
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('.', $fileName, 2);
			$fileName[0] = str_pad($fileName[0], 3, '0', STR_PAD_LEFT );
			$fileName = implode('.', $fileName);
			$fileName = $outputDir . DIRECTORY_SEPARATOR . $fileName . '.mp4';
			print_r([
				'path' => $item,
				'fileName' => $fileName,
			]);
			// 拼接文件名并转为gbk为window支持的编码
			$fileName = iconv('utf-8' , 'gbk', $fileName);
			$cmd = "ffmpeg ".($isDebug? "": "-loglevel quiet")." -i {$audio} -i {$video} -codec copy {$fileName}";
			shell_exec($cmd); // cmd可执行
		}
	}	
}

参考

相关推荐
Pocker_Spades_A1 小时前
视频不用再一张张截图:ClipSketch AI 把关键画面转成漫画,还能顺手生成文案
人工智能·音视频
星辰徐哥1 小时前
本地视频预览别只自己看:把Remotion动效项目发给客户远程验收
docker·ai·node.js·html·音视频·react·remotion
镜像视界(浙江)科技有限公司2 小时前
《视频孪生之上:二维展示终结,三维空间计算重构城市逻辑》——跨摄像连续表达 × 三角测量厘米级定位 × 动态轨迹建模,构建新一代城市空间
大数据·人工智能·算法·矩阵·音视频·空间计算
你不是我我2 小时前
【AI 测评】想用自己的声音给视频配音?Index-TTS本地部署这样做
人工智能·音视频
Ulyanov5 小时前
AudioVision Pro:基于 PySide6 + sounddevice 的实时音频可视化播放器设计
python·算法·音视频
ID34610744205 小时前
【课程设计】基于Spring Boot+Vue的校园共享无人机服务系统设计与实现-计算机毕设 附源码44219
javascript·vue.js·spring boot·python·node.js·php·课程设计
福大大架构师每日一题5 小时前
ComfyUI v0.34.0发布:视频、音频、三维、显存与合作节点全面更新
音视频
sbjdhjd7 小时前
ThinkPHP 5.0.10 缓存写入型 RCE 复盘:从手动搭建、换行绕过到源码单步验证 | 05
java·后端·安全·spring·网络安全·数据挖掘·php
en.en..7 小时前
TCP/UDP 收发流程(网络字节序---函数讲解)
开发语言·php
en.en..8 小时前
TCP/IP四层模型「数据包封装与拆包」| 网络传输
服务器·网络·php