ac / transcoding

适用于 PHP 5.3+ 的文件转码抽象组件。

0.4.4 2014-05-03 17:38 UTC

This package is not auto-updated.

Last update: 2024-09-14 14:00:54 UTC


README

Transcoding 组件是一个用于抽象文件转码工具使用的库,以及配置它们的预设。如果您想快速使用它而无需在其他代码中实现,请查看Mutate CLI 应用Symfony2 Transcoding Bundle

实现细节及示例用法

Transcoding 组件由几个部分组成。

  1. 首先是 Transcoder 类,它统一了转码过程。它提供了各种适配器、预设和转码任务的粘合剂,以便它们可以注册并交互,以一致和安全的方式转码文件。它还在任何文件转码时调度预/后/错误事件。

  2. 其次,是 Adapter 类,这些是插件,接收标准输入文件,提供一些逻辑以转码文件,并返回标准输出文件。它们可以对它们允许处理的输入/输出文件类型施加限制。

  3. 第三是 Preset 类,它们为 Adapter 在实现其转码逻辑时提供选项组合。它们也可以对它们允许处理的输入/输出文件类型施加限制。

  4. 第四是 File 实例。它们是 PHP 标准的 SplFileObject 类的扩展。这些与 Preset 实例一起是 Adapters 接收的输入。如果 Adapter 返回一个文件,它也应该是一个 AC\Transcoding\File 实例。

  5. 第五是 FileHandlerDefinition 实例。这些可以由适配器和预设指定,并定义允许作为输入和输出的文件类型。这些实例由 Transcoder 内部使用,以确保有效的输入/输出,并在未指定有效输出文件路径时辅助构建,或在提供无效路径之前捕获它,然后将其传递给适配器进行转码过程。

以下将展示上述各项的基本示例用法和实现。

Transcoder

Transcoder 执行标准化转码输入和输出的工作。它在转码文件时具体做什么由注册的预设和适配器决定。

用法

单独使用 Transcoder 很简单,因为它没有依赖关系。它可以接受来自任何地方的预设/适配器,其中一些可能需要自己的依赖关系。

$transcoder = new AC\Transcoding\Transcoder;

// ... register presets & adapters ... 
$transcoder->registerAdapter(new MyCustomFFmpegAdapter("/path/to/ffmpeg"));
$transcoder->registerPreset(new FFmpeg/WebmHDPreset);

//transcode one file using a preset
$newFile = $transcoder->transcodeWithPreset($inputFilePath, 'webm-hd', $outputFilePath);

//transcode a file with a specific adaptor and options
$newFile = $transcoder->transcodeWithAdapter($inputFilePath, 'ffmpeg', array(
	/* options */
));

适配器

适配器是现有工具集的包装器,执行任何文件转换/操作的实际工作。技术上,这些适配器可以是任何东西。常见的例子是用于音频/视频处理的 ffmpeg 和用于 PHP 中图像处理的 ImageMagick。默认情况下,库提供了包括上述提到的在内的几个常用工具的 Adapter 实现。

注册适配器

适配器可以是相当简单,也可以非常复杂。库中包含的适配器不包含库之外(除要求系统上安装某些工具外)的外部依赖关系。但是,其他适配器可能需要外部 PHP 依赖关系和特殊设置。这超出了库的处理范围。

//build your custom adapter
$adapter = new MyCoolAdapter(/* inject any dependencies */);
$transcoder->registerAdapter($adapter);

//register adapters provided with the library
$transcoder->registerAdapter(new FFmpegAdapter);
$transcoder->registerAdapter(new ImageFormatConverterAdapter);
$transcoder->registerAdapter(new ImageEffectsAdapter);

编写适配器

所有适配器都以相同的方式接收输入 - 它们只是简单地接受一个输入文件对象、一个字符串输出路径以及用于转码过程中的 Preset 实例。通常,适配器不是直接使用的,而是 Transcoder 会传递注册的预设,并根据预设定义进行有效的输入/输出检查。下面是一个非常简单的自定义适配器的示例模板。有关编写适配器的更详细文档,请参阅 adapters/ 中的 README.md

<?php
use AC\Transcoding\Adapter;
use AC\Transcoding\File;
use AC\Transcoding\Preset;

class FooAdapter extends Adapter {
	protected $name = 'foo';
	protected $description = "A made-up adapter for documentation purposes.";
	
	public function transcodeFile(File $inFile, Preset $preset, $outFilePath) {
		
		//do actual transcode process, however that needs to happen for this adapter
		
		//return a new file instance for the created file
		return new File($outFilePath);
	}
}

实现命令行工具

许多文件转换工具都作为命令行可执行文件提供。编写代码以安全并一致地在不同环境中执行命令行进程已经通过 Symfony\Component\Process 组件得到了很好的实现,该组件包含在这个库中。如果您想实现需要使用命令行的工具,我们强烈建议您使用这个库而不是编写自定义代码。有关 Symfony\Component\Process 组件的更多信息,请参阅此处

例如,FFmpeg 和 Handbrake 适配器使用 Symfony\Component\Process 组件实际执行其命令行进程。一般的流程如下所示

//method of an adapter class
public function transcodeFile(File $inFile, Preset $preset, $outFilePath) {
	// ... parse the $preset object to assemble a command string in $commandString ...
	
	//use the Process component to build a process instance with the command string
	$process = new \Symfony\Component\Process\Process($commandString);
	
	//if this could be a long-running process, be sure to increase the timeout limit accordingly
	$process->setTimeout(3600);

	//pass an anonymous function to the process so the adapter can get output as it occurs
	$result = $process->run();
    $output = $process->getOutput();

	//check for error status return
	if(!$process->isSuccessful()) {
		throw new \RuntimeException($process->getExitCodeText());
	}
	
	return new File($outputFilePath);
}

预设

预设通过将常见的选项和需求捆绑在一起来简化转码过程。库中提供了几个预设,用于使用流行工具进行常见类型的文件转换。

有关更详细的文档和可用的模板,请参阅 presets/ 中的 README.md

注册预设

预设不应有依赖关系,因为它们实际上只是将选项捆绑在一起的机制,这些选项将被传递给适配器。您可以通过两种方式声明/注册预设

//instantiate inline preset
$transcoder->registerPreset(new \AC\Transcoding\Preset('preset_name', 'required_adapter_name', array(/* preset options */), array(/* FileHandlerDefinition options */)));

//pre-defined preset which extends the Preset class above and defines it's settings internally
$transcoder->registerPreset(new Mp4_HD_720Preset);

编写预设

预设可以通过两种方式声明。您可以通过实例化预设类并传递所需选项来创建一个,或者您可以扩展基 Preset 类。库提供了许多扩展基 Preset 类的预设,以便更容易使用。预设需要两个主要部分,首先是实际的预设选项,这些选项将传递给适配器,其次是两个 FileHandlerDefinition 实例,它们标准化了接受的输入/输出格式。例如,查看为生成用于 iOS 设备的视频的 Handbrake 预设

<?php

namespace AC\Transcoding\Preset\Handbrake;

use AC\Transcoding\Preset;

/**
 * For more information on this preset please visit this link: https://trac.handbrake.fr/wiki/BuiltInPresets#classic
 */
class ClassicPreset extends BasePreset
{
    protected $key = "handbrake.classic";
    protected $name = "Classic Preset";
    protected $description = "HandBrake's traditional, faster, lower-quality settings. ";

    /**
     * Specify the options for this specific preset
     */
    public function configure()
    {
        $this->setOptions(array(
            'video-library-encoder' => 'x264',
            'video-bitrate' => '1000',
            'select-audio-tracks' => '1',
            'audio-encoder' => 'faac',
            'audio-bitrate' => '160',
            'surround-sound-downmixing' => 'dp12',
            'audio-samplerate' => 'Auto',
            'dynamic-range-compression' => '0.0',
            'format' => 'mp4',
        ));
    }
}	

FileHandlerDefinition 实例

适配器和预设都可以指定 FileHandlerDefintion 实例以限制接受的输入和输出文件类型。转码器使用 FileHandlerDefinition 实例以标准化的方式处理输入和输出。FileHandlerDefinition 实例可以设置对允许或拒绝的输入扩展名、MIME 类型、MIME 编码和其他属性的约束。

FileHandlerDefinition 实例还用于由转码器组装输出文件路径,该路径将传递给适配器,如果运行作业时未向转码器提供路径。

默认情况下,所有 AdapterPreset 类都会返回接受任何格式文件的输入和输出文件的 FileHandlerDefinition 实例。

事件

转码器也是 Symfony EventDispatcher 的一个实例。它在转码过程中发生的几乎所有事情上都会触发事件,例如,在过程前后,如果发生错误,以及任何文件或目录被修改时。您可以为这些事件注册监听器以实现其他重要功能,如日志记录。

待办:定义/解释所有事件