В современной практике автоматизации бизнес-процессов часто возникает задача хранения медиаконтента непосредственно в информационной базе или во внешних хранилищах, связанных с 1С. Пользователи могут прикреплять к карточкам товаров, отчетам о выполненных работах или карточкам контрагентов видеофайлы самых разных форматов: .avi, .mkv, .mov, .wmv и другие. Однако для унификации отображения видео на различных устройствах (включая мобильные клиенты, тонкие клиенты и веб-интерфейс в браузере) требуется единый стандарт. Таким стандартом де-факто стал формат MP4 (с видеокодеком H.264 и аудиокодеком AAC).
В этой статье мы подробно разберем, как силами платформы 1С и свободно распространяемой кроссплатформенной консольной утилиты FFmpeg организовать надежную, производительную и полностью автоматическую конвертацию любых входящих видеофайлов в формат .mp4.
Прежде чем перейти к написанию программного кода, проанализируем ситуацию и выберем оптимальную архитектуру. Конвертация видео — это крайне ресурсоемкая операция, которая нагружает центральный процессор и дисковую подсистему сервера. Если выполнять конвертацию в основном потоке непосредственно в момент прикрепления файла пользователем, интерфейс программы зависнет, что вызовет негативную реакцию.
Рассмотрим два основных сценария реализации этой задачи:
.mp4 и меняет статус на "Сконвертировано". В случае ошибки фиксируется лог для администратора. Такой подход гарантирует, что работа пользователей не будет заблокирована.Разберем по шагам, как подготовить утилиту FFmpeg к работе. Часто разработчики совершают ошибку, сохраняя Windows-версию утилиты (ffmpeg.exe) в макет конфигурации в виде двоичных данных и выгружая ее на диск перед вызовом. В современных реалиях, когда многие серверы 1С работают под управлением операционных систем семейства Linux (Ubuntu, Astra Linux, РЕД ОС), такой подход приведет к неработоспособности системы.
Для обеспечения кроссплатформенности мы применим комбинированный метод: выясним тип платформы сервера и построим путь к утилите динамически. Если сервер работает на Linux, правильнее использовать системный пакет FFmpeg, установленный администратором через стандартный менеджер пакетов (например, с помощью команды sudo apt install ffmpeg). Для Windows-сервера мы можем выгружать исполняемый файл из общего макета или обращаться к заранее установленному пути.
Посмотрим на пример функции, определяющей путь к исполняемому файлу FFmpeg на сервере:
Функция ПолучитьПутьКFFmpeg() Экспорт
СистемнаяИнфо = Новый СистемнаяИнформация;
ТипПлатформы = СистемнаяИнфо.ТипПлатформы;
// Проверяем, под какой ОС запущен сервер 1С
Если ТипПлатформы = ТипПлатформыКомпьютера.Windows_x86
Или ТипПлатформы = ТипПлатформыКомпьютера.Windows_x86_64 Тогда
// Для Windows выгружаем из макета во временный каталог, если файла там еще нет
ПутьКФайлу = КаталогВременныхФайлов() + "ffmpeg.exe";
ФайлНаДиске = Новый Файл(ПутьКФайлу);
Если Не ФайлНаДиске.Существует() Тогда
ДвоичныеДанныеМакет = УправлениеФайламиПереопределяемый.ПолучитьМакетFFmpeg();
ДвоичныеДанныеМакет.Записать(ПутьКФайлу);
КонецЕсли;
Возврат """" + ПутьКФайлу + """";
ИначеЕсли ТипПлатформы = ТипПлатформыКомпьютера.Linux_x86
Или ТипПлатформы = ТипПлатформыКомпьютера.Linux_x86_64 Тогда
// В Linux утилита должна быть установлена в системе. Обращаемся напрямую по имени команды
Возврат "ffmpeg";
Иначе
ВызватьИсключение "Неподдерживаемая операционная система сервера для конвертации видео.";
КонецЕсли;
КонецФункции
Процесс конвертации можно настроить по-разному. Если бездумно перекодировать каждый файл, процессор сервера будет постоянно загружен на 100%. Выясним причину, как можно этого избежать.
Очень часто исходные файлы уже содержат видеопоток H.264 и аудиопоток AAC, но упакованы в контейнеры .mkv или .mov. В этом случае нам не нужно выполнять декодирование и повторное сжатие. Достаточно выполнить операцию ремуксинга (remuxing) — быстрой смены контейнера без изменения самих потоков данных. Это происходит практически мгновенно (за доли секунды) и не создает нагрузки на процессор. Команда для этого выглядит так:
ffmpeg -i input.mkv -c:v copy -c:a copy output.mp4
Если же исходный файл записан в старых форматах (например, MPEG-4 Visual, DivX или WMV), нам придется провести полноценное перекодирование. Для того чтобы сконвертированное видео могло воспроизводиться в веб-клиенте 1С без предварительного скачивания всего файла целиком, критически важно использовать флаг -movflags +faststart. Этот флаг переносит индексную таблицу (moov atom) в начало файла, позволяя браузеру запускать потоковое видео мгновенно.
Рассмотрим оптимальную универсальную команду конвертации:
ffmpeg -i input.avi -c:v libx264 -preset fast -movflags +faststart -c:a aac -b:a 128k output.mp4
При интеграции внешних программ разработчики часто сталкиваются с проблемой: как понять, успешно ли завершилась операция? Обычный метод ЗапуститьПриложение в синхронном режиме возвращает код возврата, но не показывает текстовое описание ошибки. Кроме того, утилита FFmpeg выводит весь технический лог и сообщения об ошибках в поток стандартного вывода ошибок (stderr), а не в стандартный вывод (stdout).
Разберем подробнее, как запустить процесс конвертации, дождаться его окончания и проанализировать возникшие ошибки. Мы перенаправим поток вывода ошибок в отдельный текстовый файл, который затем прочитаем средствами 1С.
Реализуем процедуру конвертации на сервере:
Функция СконвертироватьВидеоВMP4(ПутьКИсходномуФайлу, ПутьКВыходномуФайлу, СообщениеОбОшибке) Экспорт
ПутьКFFmpeg = ПолучитьПутьКFFmpeg();
КаталогВременныхФайлов = КаталогВременныхФайлов();
ИмяФайлаЛогов = КаталогВременныхФайлов + "ffmpeg_error_" + Строка(Новый УникальныйИдентификатор) + ".log";
// Формируем параметры запуска.
// Перенаправляем поток stderr (2) в файл логов.
// Флаг -y автоматически перезаписывает выходной файл, если он существует.
ПараметрыЗапуска = СтрШаблон("%1 -i ""%2"" -c:v libx264 -preset fast -movflags +faststart -c:a aac -y ""%3"" 2>""%4""",
ПутьКFFmpeg,
ПутьКИсходномуФайлу,
ПутьКВыходномуФайлу,
ИмяФайлаЛогов);
СистемнаяИнфо = Новый СистемнаяИнформация;
ТипПлатформы = СистемнаяИнфо.ТипПлатформы;
// Запускаем через командную строку операционной системы
Если ТипПлатформы = ТипПлатформыКомпьютера.Windows_x86
Или ТипПлатформы = ТипПлатформыКомпьютера.Windows_x86_64 Тогда
СтрокаЗапуска = "cmd.exe /c " + ПараметрыЗапуска;
Иначе
СтрокаЗапуска = "sh -c '" + ПараметрыЗапуска + "'";
КонецЕсли;
КодВозврата = Неопределено;
// Запуск процесса с ожиданием завершения
ЗапуститьПриложение(СтрокаЗапуска, , Истина, КодВозврата);
// Анализируем результаты работы
Успешно = (КодВозврата = 0);
ФайлЛогов = Новый Файл(ИмяФайлаЛогов);
Если ФайлЛогов.Существует() Тогда
Если Не Успешно Тогда
// Читаем текст ошибки из лог-файла
ТекстовыйДокументЛога = Новый ТекстовыйДокумент;
ТекстовыйДокументЛога.Прочитать(ИмяФайлаЛогов, КодировкаТекста.UTF8);
СообщениеОбОшибке = ТекстовыйДокументЛога.ПолучитьТекст();
КонецЕсли;
// Удаляем временный файл лога
Попытка
УдалитьФайлы(ИмяФайлаЛогов);
Исключение
// Запись в журнал регистрации, если не удалось удалить временный файл
ЗаписьЖурналаРегистрации("КонвертацияВидео.ОчисткаВременныхФайлов",
УровеньЖурналаРегистрации.Предупреждение, , ,
ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
Возврат Успешно;
КонецФункции
Для того чтобы встроить этот механизм в типовую или самописную конфигурацию, логично использовать функционал фонового выполнения задач. Если в вашей конфигурации используется Библиотека стандартных подсистем (БСП), мы можем задействовать подсистему "Файловые функции" или стандартный механизм регламентных заданий.
Опишем типовой алгоритм работы фонового регламентного задания:
Справочник.НоменклатураПрисоединенныеФайлы) записи, у которых расширение файла отличается от mp4, а в специальном добавленном реквизите СтатусКонвертации установлено значение Перечисление.СтатусыКонвертацииВидео.ОжидаетОбработки.СконвертироватьВидеоВMP4.mp4, а статус переводится в Обработано. Старый исходный файл удаляется (или перемещается в архив для подстраховки).ОшибкаОбработки, а подробное описание ошибки записывается в Журнал регистрации 1С с указанием ссылки на карточку файла.Посмотрим на пример реализации такого фонового обработчика:
Процедура ВыполнитьКонвертациюВидеоНаСервере() Экспорт
// Запрос для выбора файлов в очереди
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Файлы.Ссылка КАК Ссылка,
| Файлы.Наименование КАК Наименование,
| Файлы.Расширение КАК Расширение
|ИЗ
| Справочник.НоменклатураПрисоединенныеФайлы КАК Файлы
|ГДЕ
| Файлы.СтатусКонвертации = ЗНАЧЕНИЕ(Перечисление.СтатусыКонвертацииВидео.ОжидаетОбработки)
| И Файлы.ПометкаУдаления = ЛОЖЬ";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
СсылкаНаФайл = Выборка.Ссылка;
ИмяФайла = Выборка.Наименование;
Расширение = Выборка.Расширение;
// Создаем уникальные имена файлов на диске сервера
УникальныйИдентификатор = Новый УникальныйИдентификатор;
ВременныйВходнойФайл = КаталогВременныхФайлов() + "input_" + Строка(УникальныйИдентификатор) + "." + Расширение;
ВременныйВыходнойФайл = КаталогВременныхФайлов() + "output_" + Строка(УникальныйИдентификатор) + ".mp4";
// Получаем двоичные данные исходного файла и записываем на диск
ДвоичныеДанныеФайла = РаботаСФайлами.ПолучитьДвоичныеДанныеФайла(СсылкаНаФайл);
ДвоичныеДанныеФайла.Записать(ВременныйВходнойФайл);
СообщениеОбОшибке = "";
Успешно = СконвертироватьВидеоВMP4(ВременныйВходнойФайл, ВременныйВыходнойФайл, СообщениеОбОшибке);
Если Успешно Тогда
// Загружаем готовый mp4 файл обратно в 1С
НовыеДвоичныеДанные = Новый ДвоичныеДанные(ВременныйВыходнойФайл);
ОбъектФайл = СсылкаНаФайл.ПолучитьОбъект();
ОбъектФайл.ЗаписатьДанныеФайла(НовыеДвоичныеДанные);
ОбъектФайл.Расширение = "mp4";
ОбъектФайл.СтатусКонвертации = Перечисления.СтатусыКонвертацииВидео.Обработано;
ОбъектФайл.Записать();
ЗаписьЖурналаРегистрации("КонвертацияВидео.Успех",
УровеньЖурналаРегистрации.Информация,
СсылкаНаФайл.Метаданные(), СсылкаНаФайл,
"Файл успешно сконвертирован в формат MP4: " + ИмяФайла);
Иначе
// Фиксируем ошибку в карточке файла и журнале регистрации
ОбъектФайл = СсылкаНаФайл.ПолучитьОбъект();
ОбъектФайл.СтатусКонвертации = Перечисления.СтатусыКонвертацииВидео.ОшибкаОбработки;
ОбъектФайл.ОписаниеОшибкиКонвертации = СообщениеОбОшибке;
ОбъектФайл.Записать();
ЗаписьЖурналаРегистрации("КонвертацияВидео.Ошибка",
УровеньЖурналаРегистрации.Ошибка,
СсылкаНаФайл.Метаданные(), СсылкаНаФайл,
"Не удалось сконвертировать файл: " + ИмяФайла + Символы.ПС + СообщениеОбОшибке);
КонецЕсли;
// Обязательно очищаем за собой временные файлы на диске сервера
Попытка
УдалитьФайлы(ВременныйВходнойФайл);
Если Успешно Тогда
УдалитьФайлы(ВременныйВыходнойФайл);
КонецЕсли;
Исключение
ЗаписьЖурналаРегистрации("КонвертацияВидео.ОчисткаВременныхФайлов",
УровеньЖурналаРегистрации.Предупреждение, , ,
ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Мы спроектировали и детально разобрали отказоустойчивое решение по конвертации видеофайлов в формат MP4 силами платформы 1С и утилиты FFmpeg. Такой подход позволяет полностью удовлетворить требования бизнеса, не нагружая пользователей ручной конвертацией и сторонними инструментами.
Для успешного внедрения этого решения помните о следующих правилах:
-movflags +faststart для оптимизации просмотра медиаконтента в веб-интерфейсе 1С.