crossknowledge/subconverter-bundle
Installation:
composer require crossknowledge/subconverter-bundle
Register the bundle in config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 3.x):
CrossKnowledge\SubConverterBundle\CrossKnowledgeSubConverterBundle::class => ['all' => true],
First Use Case: Convert an SRT file to WebVTT in a controller:
use Symfony\Component\HttpFoundation\File\UploadedFile;
public function convertSubtitles(UploadedFile $file, string $format)
{
$converter = $this->get('crossknowledge.subconverterbundle.converter');
$outputPath = sys_get_temp_dir() . '/converted.' . $format;
$converter->convert($file->getPathname(), $outputPath, $format, false);
return new FileResponse($outputPath);
}
Key Service:
The crossknowledge.subconverterbundle.converter service is the entry point. Check its configuration in services.yaml (Symfony 4+) or services.xml (Symfony 3.x) for dependencies.
File Handling:
UploadedFile or raw paths. Validate input format before conversion:
$supportedFormats = ['srt', 'webvtt', 'ttaf1', 'txt'];
if (!in_array($inputFormat, $supportedFormats)) {
throw new \InvalidArgumentException('Unsupported input format');
}
Batch Processing: Loop through uploaded files (e.g., from a form with multiple files):
foreach ($request->files->get('subtitles') as $file) {
$outputPath = $this->generateOutputPath($file, 'webvtt');
$this->get('crossknowledge.subconverterbundle.converter')->convert(
$file->getPathname(),
$outputPath,
'webvtt',
true
);
}
Integration with Storage:
Use Symfony’s Filesystem or Storage components to handle output paths dynamically:
$storage = $this->get('oneup_flysystem.storage_filesystem');
$file = $storage->write('subtitles/converted.webvtt', $convertedContent);
Command-Line Conversion: Create a console command for background processing:
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ConvertSubtitlesCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output)
{
$converter = $this->get('crossknowledge.subconverterbundle.converter');
$converter->convert(
$input->getArgument('input'),
$input->getArgument('output'),
$input->getArgument('format'),
$input->getOption('bom')
);
$output->writeln('Conversion complete!');
}
}
Event-Driven Workflows: Trigger conversions after file uploads via Symfony events:
// config/services.yaml
App\EventListener\SubtitleUploadListener:
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
Format Limitations:
$allowedOutputFormats = ['srt', 'webvtt', 'txt'];
if (!in_array($outputFormat, $allowedOutputFormats)) {
throw new \RuntimeException('TTAF1 output not supported');
}
BOM Handling:
includeBom only affects output for txt and webvtt. Ignoring it for SRT/TTAF1 may cause encoding issues in downstream tools.File Locking:
$tempPath = tempnam(sys_get_temp_dir(), 'sub_') . '.' . $outputFormat;
Encoding Issues:
mb_convert_encoding:
$content = mb_convert_encoding(file_get_contents($inputPath), 'UTF-8', 'ISO-8859-1');
Deprecated Methods:
# config/services.yaml
CrossKnowledge\SubConverterBundle\Service\Converter:
arguments:
$someDependency: '@new_service'
Log Conversion Steps: Decorate the converter service to log inputs/outputs:
// src/Service/ConverterLogger.php
class ConverterLogger implements ConverterInterface
{
private $decorated;
private $logger;
public function __construct(ConverterInterface $converter, LoggerInterface $logger)
{
$this->decorated = $converter;
$this->logger = $logger;
}
public function convert($input, $output, $format, $bom)
{
$this->logger->info('Converting', [
'input' => $input,
'output' => $output,
'format' => $format,
]);
return $this->decorated->convert($input, $output, $format, $bom);
}
}
Validate Output: Use a post-conversion validator (e.g., check WebVTT structure with regex):
private function validateWebVTT(string $content): bool
{
return preg_match('/^WEBVTT\n(?:[^\S\r\n]+\r?\n)?/m', $content) === 1;
}
Fallback for Unsupported Formats:
Use a fallback converter (e.g., spatie/subtitle) for unsupported formats:
if (!in_array($format, ['srt', 'webvtt', 'txt'])) {
$fallbackConverter = new \Spatie\Subtitle\Converter();
return $fallbackConverter->convert($inputPath, $outputPath, $format);
}
Custom Format Support: Extend the bundle by creating a new converter class and overriding the service:
// src/Service/CustomConverter.php
class CustomConverter implements ConverterInterface
{
public function convert($input, $output, $format, $bom)
{
if ($format === 'custom') {
// Implement custom logic
return $this->writeCustomFormat($input, $output);
}
// Delegate to original converter
return $this->get('crossknowledge.subconverterbundle.converter')->convert($input, $output, $format, $bom);
}
}
Pre/Post-Processing Hooks: Use Symfony’s compiler passes or event listeners to inject logic:
// src/EventListener/SubtitleEventListener.php
class SubtitleEventListener
{
public function onSubtitleConvert(SubtitleConvertEvent $event)
{
$event->setInput($this->preProcess($event->getInput()));
}
}
Configuration Overrides:
Override default settings (e.g., temp directory) via config/packages/cross_knowledge_sub_converter.yaml:
cross_knowledge_sub_converter:
temp_dir: '%kernel.project_dir%/var/subtitles_temp'
How can I help you explore Laravel packages today?