From 83762aaab2b6061895efa77c13aba0ace6dfa1d7 Mon Sep 17 00:00:00 2001 From: Jack Lau Date: Fri, 16 Jan 2026 21:36:38 +0800 Subject: [PATCH 1/3] fix wrong encoder in output file by transcoder_bmf - Use input pix_fmt and codec when codec is auto for bmf - Show pixel format in info_view_page - Remove video, audio, format setting in ai processing page Signed-off-by: Jack Lau --- src/builder/include/ai_processing_page.h | 21 - src/builder/include/info_view_page.h | 2 + src/builder/src/ai_processing_page.cpp | 122 +--- src/builder/src/info_view_page.cpp | 16 +- src/common/include/info.h | 1 + src/common/src/info.cpp | 8 + src/resources/lang_chinese.qm | Bin 22974 -> 22582 bytes src/resources/lang_chinese.ts | 844 ++++++++++++++--------- src/transcoder/src/transcoder_bmf.cpp | 92 ++- 9 files changed, 634 insertions(+), 472 deletions(-) diff --git a/src/builder/include/ai_processing_page.h b/src/builder/include/ai_processing_page.h index 2776d927..7b61c5cd 100644 --- a/src/builder/include/ai_processing_page.h +++ b/src/builder/include/ai_processing_page.h @@ -24,7 +24,6 @@ #include "progress_widget.h" #include "batch_output_widget.h" #include "batch_mode_helper.h" -#include "bitrate_widget.h" #include #include #include @@ -56,7 +55,6 @@ private slots: void OnInputFileSelected(const QString &filePath); void OnOutputFileSelected(const QString &filePath); void OnAlgorithmChanged(int index); - void OnFormatChanged(int index); void OnProcessClicked(); void OnProcessFinished(bool success); @@ -90,25 +88,6 @@ private slots: QLabel *upscaleFactorLabel; QSpinBox *upscaleFactorSpinBox; - // Video settings section - QGroupBox *videoGroupBox; - QLabel *videoCodecLabel; - QComboBox *videoCodecComboBox; - QLabel *videoBitrateLabel; - BitrateWidget *videoBitrateWidget; - - // Audio settings section - QGroupBox *audioGroupBox; - QLabel *audioCodecLabel; - QComboBox *audioCodecComboBox; - QLabel *audioBitrateLabel; - BitrateWidget *audioBitrateWidget; - - // Format section - QGroupBox *formatGroupBox; - QLabel *formatLabel; - QComboBox *formatComboBox; - // Progress section ProgressWidget *progressWidget; diff --git a/src/builder/include/info_view_page.h b/src/builder/include/info_view_page.h index c912a8e7..3884ca4d 100644 --- a/src/builder/include/info_view_page.h +++ b/src/builder/include/info_view_page.h @@ -72,6 +72,8 @@ private slots: QLabel *colorSpaceValue; QLabel *videoCodecLabel; QLabel *videoCodecValue; + QLabel *pixelFormatLabel; + QLabel *pixelFormatValue; QLabel *videoBitRateLabel; QLabel *videoBitRateValue; QLabel *frameRateLabel; diff --git a/src/builder/src/ai_processing_page.cpp b/src/builder/src/ai_processing_page.cpp index 9dc56d0c..7f5bdfa8 100644 --- a/src/builder/src/ai_processing_page.cpp +++ b/src/builder/src/ai_processing_page.cpp @@ -84,13 +84,7 @@ void AIProcessingPage::OnPageActivated() { } void AIProcessingPage::OnInputFileChanged(const QString &newPath) { - QString ext = GetFileExtension(newPath); - if (!ext.isEmpty()) { - int index = formatComboBox->findText(ext); - if (index >= 0) { - formatComboBox->setCurrentIndex(index); - } - } + Q_UNUSED(newPath); // Update output path when input changes UpdateOutputPath(); } @@ -102,7 +96,7 @@ void AIProcessingPage::OnOutputPathUpdate() { void AIProcessingPage::OnPageDeactivated() { BasePage::OnPageDeactivated(); HandleSharedDataUpdate(inputFileSelector->GetLineEdit(), outputFileSelector->GetLineEdit(), - formatComboBox->currentText()); + GetFileExtension(inputFileSelector->GetFilePath())); } void AIProcessingPage::SetupUI() { @@ -168,63 +162,6 @@ void AIProcessingPage::SetupUI() { algoSettingsLayout->addWidget(algoSettingsStack, 0, 0, 1, 2); mainLayout->addWidget(algoSettingsGroupBox); - // Video Settings Section - videoGroupBox = new QGroupBox(tr("Video Settings"), this); - QGridLayout *videoLayout = new QGridLayout(videoGroupBox); - videoLayout->setSpacing(10); - - videoCodecLabel = new QLabel(tr("Codec:"), videoGroupBox); - videoCodecComboBox = new QComboBox(videoGroupBox); - videoCodecComboBox->addItems({"auto", "libx264", "libx265", "libvpx-vp9", "copy"}); - videoCodecComboBox->setCurrentText("auto"); - - videoBitrateLabel = new QLabel(tr("Bitrate:"), videoGroupBox); - videoBitrateWidget = new BitrateWidget(BitrateWidget::Video, videoGroupBox); - - videoLayout->addWidget(videoCodecLabel, 0, 0); - videoLayout->addWidget(videoCodecComboBox, 0, 1); - videoLayout->addWidget(videoBitrateLabel, 1, 0); - videoLayout->addWidget(videoBitrateWidget, 1, 1); - - mainLayout->addWidget(videoGroupBox); - - // Audio Settings Section - audioGroupBox = new QGroupBox(tr("Audio Settings"), this); - QGridLayout *audioLayout = new QGridLayout(audioGroupBox); - audioLayout->setSpacing(10); - - audioCodecLabel = new QLabel(tr("Codec:"), audioGroupBox); - audioCodecComboBox = new QComboBox(audioGroupBox); - audioCodecComboBox->addItems({"auto", "aac", "libmp3lame", "libopus", "copy"}); - audioCodecComboBox->setCurrentText("auto"); - - audioBitrateLabel = new QLabel(tr("Bitrate:"), audioGroupBox); - audioBitrateWidget = new BitrateWidget(BitrateWidget::Audio, audioGroupBox); - - audioLayout->addWidget(audioCodecLabel, 0, 0); - audioLayout->addWidget(audioCodecComboBox, 0, 1); - audioLayout->addWidget(audioBitrateLabel, 1, 0); - audioLayout->addWidget(audioBitrateWidget, 1, 1); - - mainLayout->addWidget(audioGroupBox); - - // Format Section - formatGroupBox = new QGroupBox(tr("File Format"), this); - QHBoxLayout *formatLayout = new QHBoxLayout(formatGroupBox); - - formatLabel = new QLabel(tr("Format:"), formatGroupBox); - formatComboBox = new QComboBox(formatGroupBox); - formatComboBox->addItems({"mp4", "mkv", "avi", "mov", "flv", "webm", "ts", "jpg", "png"}); - formatComboBox->setCurrentText("mp4"); - connect(formatComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &AIProcessingPage::OnFormatChanged); - - formatLayout->addWidget(formatLabel); - formatLayout->addWidget(formatComboBox); - formatLayout->addStretch(); - - mainLayout->addWidget(formatGroupBox); - // Output File Selector outputFileSelector = new FileSelectorWidget( tr("Output File"), @@ -285,15 +222,6 @@ void AIProcessingPage::OnInputFileSelected(const QString &filePath) { mainWindow->GetSharedData()->SetInputFilePath(filePath); } - // Set default format to same as input file - QString ext = GetFileExtension(filePath); - if (!ext.isEmpty()) { - int index = formatComboBox->findText(ext); - if (index >= 0) { - formatComboBox->setCurrentIndex(index); - } - } - // Update output path UpdateOutputPath(); } @@ -311,16 +239,11 @@ void AIProcessingPage::OnAlgorithmChanged(int index) { algoSettingsStack->setCurrentIndex(index); } -void AIProcessingPage::OnFormatChanged(int index) { - Q_UNUSED(index); - UpdateOutputPath(); -} - void AIProcessingPage::OnProcessClicked() { // Check if batch mode is active if (batchModeHelper->IsBatchMode()) { // Batch mode: Add to queue - QString format = formatComboBox->currentText(); + QString format = GetFileExtension(inputFileSelector->GetFilePath()); batchModeHelper->AddToQueue(format); return; } @@ -362,7 +285,7 @@ void AIProcessingPage::UpdateOutputPath() { if (!inputPath.isEmpty()) { OpenConverter *mainWindow = qobject_cast(window()); if (mainWindow && mainWindow->GetSharedData()) { - QString format = formatComboBox->currentText(); + QString format = GetFileExtension(inputPath); QString outputPath = mainWindow->GetSharedData()->GenerateOutputPath(format); outputFileSelector->SetFilePath(outputPath); processButton->setEnabled(true); @@ -385,25 +308,8 @@ EncodeParameter* AIProcessingPage::CreateEncodeParameter() { encodeParam->set_upscale_factor(upscaleFactorSpinBox->value()); } - // Set video codec and bitrate - QString videoCodec = videoCodecComboBox->currentText(); - if (videoCodec != "auto") - encodeParam->set_video_codec_name(videoCodec.toStdString()); - - int videoBitrate = videoBitrateWidget->GetBitrate(); - if (videoBitrate > 0) { - encodeParam->set_video_bit_rate(videoBitrate); - } - - // Set audio codec and bitrate - QString audioCodec = audioCodecComboBox->currentText(); - if (audioCodec != "auto") - encodeParam->set_audio_codec_name(audioCodec.toStdString()); - - int audioBitrate = audioBitrateWidget->GetBitrate(); - if (audioBitrate > 0) { - encodeParam->set_audio_bit_rate(audioBitrate); - } + // Video/audio codec and bitrate are auto-detected from input file + // No user configuration needed for AI processing return encodeParam; } @@ -423,22 +329,6 @@ void AIProcessingPage::RetranslateUi() { algoSettingsGroupBox->setTitle(tr("Algorithm Settings")); upscaleFactorLabel->setText(tr("Upscale Factor:")); - // Update video settings section - videoGroupBox->setTitle(tr("Video Settings")); - videoCodecLabel->setText(tr("Codec:")); - videoBitrateLabel->setText(tr("Bitrate:")); - videoBitrateWidget->RetranslateUi(); - - // Update audio settings section - audioGroupBox->setTitle(tr("Audio Settings")); - audioCodecLabel->setText(tr("Codec:")); - audioBitrateLabel->setText(tr("Bitrate:")); - audioBitrateWidget->RetranslateUi(); - - // Update format section - formatGroupBox->setTitle(tr("File Format")); - formatLabel->setText(tr("Format:")); - // Update output file selector outputFileSelector->setTitle(tr("Output File")); outputFileSelector->SetPlaceholder(tr("Output file path...")); diff --git a/src/builder/src/info_view_page.cpp b/src/builder/src/info_view_page.cpp index 85c1743e..f5d49a48 100644 --- a/src/builder/src/info_view_page.cpp +++ b/src/builder/src/info_view_page.cpp @@ -86,6 +86,8 @@ void InfoViewPage::SetupUI() { colorSpaceValue = new QLabel("-", this); videoCodecLabel = new QLabel(tr("Video Codec:"), this); videoCodecValue = new QLabel("-", this); + pixelFormatLabel = new QLabel(tr("Pixel Format:"), this); + pixelFormatValue = new QLabel("-", this); videoBitRateLabel = new QLabel(tr("Bit Rate:"), this); videoBitRateValue = new QLabel("-", this); frameRateLabel = new QLabel(tr("Frame Rate:"), this); @@ -101,10 +103,12 @@ void InfoViewPage::SetupUI() { videoLayout->addWidget(colorSpaceValue, 3, 1); videoLayout->addWidget(videoCodecLabel, 4, 0); videoLayout->addWidget(videoCodecValue, 4, 1); - videoLayout->addWidget(videoBitRateLabel, 5, 0); - videoLayout->addWidget(videoBitRateValue, 5, 1); - videoLayout->addWidget(frameRateLabel, 6, 0); - videoLayout->addWidget(frameRateValue, 6, 1); + videoLayout->addWidget(pixelFormatLabel, 5, 0); + videoLayout->addWidget(pixelFormatValue, 5, 1); + videoLayout->addWidget(videoBitRateLabel, 6, 0); + videoLayout->addWidget(videoBitRateValue, 6, 1); + videoLayout->addWidget(frameRateLabel, 7, 0); + videoLayout->addWidget(frameRateValue, 7, 1); mainLayout->addWidget(videoGroupBox); @@ -213,6 +217,7 @@ void InfoViewPage::DisplayInfo(QuickInfo *quickInfo) { heightValue->setText(QString("%1 px").arg(quickInfo->height)); colorSpaceValue->setText(QString::fromStdString(quickInfo->colorSpace)); videoCodecValue->setText(QString::fromStdString(quickInfo->videoCodec)); + pixelFormatValue->setText(QString::fromStdString(quickInfo->pixelFormat)); videoBitRateValue->setText(FormatBitrate(quickInfo->videoBitRate)); frameRateValue->setText(QString("%1 fps").arg(quickInfo->frameRate, 0, 'f', 2)); } else { @@ -221,6 +226,7 @@ void InfoViewPage::DisplayInfo(QuickInfo *quickInfo) { heightValue->setText("-"); colorSpaceValue->setText("-"); videoCodecValue->setText("-"); + pixelFormatValue->setText("-"); videoBitRateValue->setText("-"); frameRateValue->setText("-"); } @@ -249,6 +255,7 @@ void InfoViewPage::ClearInfo() { heightValue->setText("-"); colorSpaceValue->setText("-"); videoCodecValue->setText("-"); + pixelFormatValue->setText("-"); videoBitRateValue->setText("-"); frameRateValue->setText("-"); @@ -295,6 +302,7 @@ void InfoViewPage::RetranslateUi() { heightLabel->setText(tr("Height:")); colorSpaceLabel->setText(tr("Color Space:")); videoCodecLabel->setText(tr("Video Codec:")); + pixelFormatLabel->setText(tr("Pixel Format:")); videoBitRateLabel->setText(tr("Bit Rate:")); frameRateLabel->setText(tr("Frame Rate:")); diff --git a/src/common/include/info.h b/src/common/include/info.h index 91337d31..90223818 100644 --- a/src/common/include/info.h +++ b/src/common/include/info.h @@ -36,6 +36,7 @@ typedef struct QuickInfo { std::string colorSpace; std::string videoCodec; + std::string pixelFormat; int64_t videoBitRate; double frameRate; diff --git a/src/common/src/info.cpp b/src/common/src/info.cpp index 5d113957..46315566 100644 --- a/src/common/src/info.cpp +++ b/src/common/src/info.cpp @@ -30,6 +30,7 @@ void Info::init() { quickInfo->height = 0; quickInfo->colorSpace = ""; quickInfo->videoCodec = ""; + quickInfo->pixelFormat = ""; quickInfo->videoBitRate = 0; quickInfo->frameRate = 0; @@ -82,6 +83,13 @@ void Info::send_info(char *src) { if (avCtx->streams[quickInfo->videoIdx]->codecpar->codec_id != AV_CODEC_ID_NONE) quickInfo->videoCodec = avcodec_get_name( avCtx->streams[quickInfo->videoIdx]->codecpar->codec_id); + // Get pixel format + AVPixelFormat pix_fmt = (AVPixelFormat)avCtx->streams[quickInfo->videoIdx]->codecpar->format; + if (pix_fmt != AV_PIX_FMT_NONE) { + const char *pix_fmt_name = av_get_pix_fmt_name(pix_fmt); + if (pix_fmt_name) + quickInfo->pixelFormat = pix_fmt_name; + } quickInfo->videoBitRate = avCtx->streams[quickInfo->videoIdx]->codecpar->bit_rate; quickInfo->frameRate = diff --git a/src/resources/lang_chinese.qm b/src/resources/lang_chinese.qm index b3fe4737bf827cfff40a7b82c54105cfd4b74ed1..491d9426068fd27156fddefe6063640afa0847a7 100644 GIT binary patch delta 2407 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 X0oL|~Io9xSUu)>17+cB0@45d2(<6>w diff --git a/src/resources/lang_chinese.ts b/src/resources/lang_chinese.ts index fc87fc68..0e5837bc 100644 --- a/src/resources/lang_chinese.ts +++ b/src/resources/lang_chinese.ts @@ -1,6 +1,193 @@ + + AIProcessingPage + + + Python Required + 需要 Python + + + + AI Processing requires Python 3.9 and additional packages. + +Would you like to download and install them now? +(Download size: ~550 MB, completely isolated from system Python) + AI 处理需要 Python 3.9 及其他依赖包。 + +是否现在下载并安装? +(下载大小:约 550 MB,与系统 Python 完全隔离) + + + + AI Processing Unavailable + AI 处理不可用 + + + + AI Processing features require Python to be installed. + +You can install it later by returning to this page. + AI 处理功能需要安装 Python。 + +您可以稍后返回此页面进行安装。 + + + + + Input File + 输入文件 + + + + + Select a media file or click Batch for multiple files... + 选择媒体文件或点击批量处理多个文件... + + + + + All Files (*.*) + 所有文件 (*.*) + + + + Select Media File + 选择媒体文件 + + + + + Algorithm + 算法 + + + + + Select Algorithm: + 选择算法: + + + + + Upscaler + 超分辨率 + + + + + Algorithm Settings + 算法设置 + + + + + Upscale Factor: + 放大倍数: + + + Video Settings + 视频设置 + + + Audio Settings + 音频设置 + + + Codec: + 编解码器: + + + Bitrate: + 比特率: + + + File Format + 文件格式 + + + Format: + 格式: + + + + + Output File + 输出文件 + + + + + Output file path... + 输出文件路径... + + + + + + + Process / Add to Queue + 处理 / 添加到队列 + + + + + Add to Queue + 添加到队列 + + + + Process + 处理 + + + + Processing... + 处理中... + + + + Select Output File + + + + + Success + 成功 + + + + AI processing completed successfully! + AI 处理成功完成! + + + + Error + 错误 + + + + Failed to process file. + 文件处理失败。 + + + + + Warning + 警告 + + + + Please select an input file. + 请选择输入文件。 + + + + Please select an output file. + 请选择输出文件。 + + BatchFileDialog @@ -373,13 +560,13 @@ CompressPicturePage - + Input File 输入文件 - + Select an image file... 选择图片文件... @@ -389,12 +576,13 @@ - + Compression Settings 压缩设置 - + + Output Format: 输出格式: @@ -411,7 +599,8 @@ 高度(0=自动): - + + Pixel Format: 像素格式: @@ -421,57 +610,59 @@ + Resolution: 分辨率: - + + Quality: 质量: - - + + Output 输出 - - + + Output file path will be generated automatically... 输出文件路径将自动生成... - + Image Files (*.jpg *.png *.webp *.bmp *.tiff);;All Files (*.*) 图像文件 (*.jpg *.png *.webp *.bmp *.tiff);;所有文件 (*.*) - + Save Image File 保存图像文件 - - - + + + Convert / Add to Queue 转换 / 添加到队列 - - + + Add to Queue 添加到队列 - + Converting... 转换中... - - + + Convert 转换 @@ -494,18 +685,18 @@ 保存压缩图片 - - + + Warning 警告 - + Please select an input file. 请选择输入文件。 - + Please specify an output file. 请指定输出文件。 @@ -523,7 +714,7 @@ 请选择输入和输出文件。 - + Starting conversion... 开始转换... @@ -532,13 +723,13 @@ CreateGifPage - + Input File 输入文件 - + Select a video or image sequence... 选择视频或图片序列... @@ -548,7 +739,7 @@ - + GIF Settings GIF 设置 @@ -565,20 +756,20 @@ 高度(0=自动): - - + + Output 输出 - - + + Output file path will be generated automatically... 输出文件路径将自动生成... - - + + Create GIF 创建 GIF @@ -593,51 +784,52 @@ 视频文件 (*.mp4 *.avi *.mkv *.mov *.flv *.wmv *.webm);;所有文件 (*.*) - + + Resolution: 分辨率: - + GIF Files (*.gif);;All Files (*.*) GIF 文件 (*.gif);;所有文件 (*.*) - + Save GIF File 保存 GIF 文件 - - - + + + Create GIF / Add to Queue 创建 GIF / 添加到队列 - - + + Add to Queue 添加到队列 - - + + Warning 警告 - + Please select an input file. 请选择输入文件。 - + Please specify an output file. 请指定输出文件。 - + Creating GIF... 正在创建 GIF... @@ -827,13 +1019,13 @@ ExtractAudioPage - + Input File 输入文件 - + Select a video file... 选择视频文件... @@ -843,12 +1035,13 @@ - + Audio Settings 音频设置 - + + Output Format: 输出格式: @@ -870,67 +1063,68 @@ + Bitrate: 比特率: - - + + Output File 输出文件 - - + + Output file path will be generated automatically... 输出文件路径将自动生成... - + Audio Files (*.mp3 *.aac *.ac3 *.flac *.wav *.ogg);;All Files (*.*) 音频文件 (*.mp3 *.aac *.ac3 *.flac *.wav *.ogg);;所有文件 (*.*) - + Save Audio File 保存音频文件 - - - - + + + + Extract Audio / Add to Queue 提取音频 / 添加到队列 - + Extracting... 提取中... - + Success 成功 - + Audio extracted successfully! 音频提取成功! - + Failed to extract audio. 音频提取失败。 - - + + Add to Queue 添加到队列 - + Extract Audio 提取音频 @@ -953,7 +1147,7 @@ 保存提取的音频 - + Error 错误 @@ -1006,101 +1200,107 @@ InfoViewPage - + Input File 输入文件 - + Drop a media file here or click Browse... 拖放媒体文件到此处或点击浏览... - + Browse... 浏览... - + Video Information 视频信息 - - - + + + Stream Index: 流索引: - + Width: 宽度: - + Height: 高度: - + Color Space: 色彩空间: - + Video Codec: 视频编解码器: - - - + + Pixel Format: + 像素格式: + + + + + + Bit Rate: 比特率: - - + + Frame Rate: 帧率: - - + + Audio Information 音频信息 - - + + Audio Codec: 音频编码: - - + + Channels: 声道数: - - + + Sample Format: 采样格式: - - + + Sample Rate: 采样率: @@ -1117,120 +1317,255 @@ OpenConverter - + + COMMON 常用功能 - + + Info View 信息查看 - + + Compress Picture 图片压缩 - + + Extract Audio 提取音频 - + + Cut Video 视频剪切 - + + Create GIF 创建 GIF - + + ADVANCED 高级功能 - + + Remux 封装转换 - + + Transcode 转码 - + + 📋 Queue 📋 队列 - + + View batch processing queue 查看批量处理队列 - + Language 语言 - + Transcoder 转码器 - + english 英语 - + English 英语 - + chinese 中文 - + Chinese 中文 - + Current Transcoder changed to %1 当前转码器已切换至 %1 - + Current Language changed to %1 当前语言已切换至 %1 - + FFMPEG FFMPEG - + BMF BMF - + FFTOOL FFTOOL + + AI Processing AI 处理 + + PythonInstallDialog + + + AI Processing Setup + + + + + AI Processing requires Python 3.9 and additional packages (PyTorch, BasicSR, Real-ESRGAN). + +This will download and install: +• Python 3.9 runtime (~18 MB) +• AI processing packages (~500 MB) + +The installation is completely isolated and will not affect your system Python. + + + + + Ready to install + + + + + Install + + + + + + Cancel + 取消 + + + + Cancel Installation + + + + + Are you sure you want to cancel the installation? + + + + + Not installed + + + + + Installing... + + + + + Installation complete! + + + + + Close + 关闭 + + + + Installation failed + + + + + + Retry + + + + + Python installed. Installing packages... + + + + + Installation complete! AI Processing is now ready. + + + + + Installation Complete + + + + + Python and all required packages have been installed successfully. + +A restart is required to enable AI Processing features. + + + + + Restart Now + + + + + Restart Later + + + + + Installation Failed + + + + + Failed to install Python runtime: + +%1 + +Please check your internet connection and try again. + + + QObject @@ -1268,56 +1603,56 @@ RemuxPage - + Input File 输入文件 - + Select a media file... 选择媒体文件... - + Remuxing... 重新封装中... - + Success 成功 - + File remuxed successfully! 文件重新封装成功! - - + + Error 错误 - + Failed to remux file. 重新封装文件失败。 - + Please select at least one stream to remux. 请至少选择一个流进行重新封装。 - - + + Browse... 浏览... - + Streams (Select streams to include) 流(选择要包含的流) @@ -1338,41 +1673,42 @@ - + Output Settings 输出设置 - + + Output Format: 输出格式: - - + + Output File 输出文件 - - + + Output file path will be generated automatically... 输出文件路径将自动生成... - + Media Files (*.mp4 *.mkv *.avi *.mov *.flv *.wmv *.webm *.ts *.m4v);;All Files (*.*) 媒体文件 (*.mp4 *.mkv *.avi *.mov *.flv *.wmv *.webm *.ts *.m4v);;所有文件 (*.*) - + Save Remuxed File 保存重新封装的文件 - - - + + + Remux 封装转换 @@ -1406,12 +1742,17 @@ TranscodePage - + Input File 输入文件 - + + All Files (*.*) + 所有文件 (*.*) + + + Select a media file... 选择媒体文件... @@ -1421,7 +1762,7 @@ - + Video Settings 视频设置 @@ -1431,9 +1772,8 @@ 选择媒体文件或点击批量处理多个文件... - Media Files (*.mp4 *.avi *.mkv *.mov *.flv *.wmv *.webm *.ts *.m4v);;All Files (*.*) - 媒体文件 (*.mp4 *.avi *.mkv *.mov *.flv *.wmv *.webm *.ts *.m4v);;所有文件 (*.*) + 媒体文件 (*.mp4 *.avi *.mkv *.mov *.flv *.wmv *.webm *.ts *.m4v);;所有文件 (*.*) @@ -1442,15 +1782,16 @@ - - - + + + Codec: 编解码器: - - + + + Bitrate: 比特率: @@ -1463,7 +1804,8 @@ 自动 - + + Resolution: 分辨率: @@ -1472,246 +1814,106 @@ x - + + Pixel Format: 像素格式: - - + + Audio Settings 音频设置 - - + + Preset 预设 - - + + Preset: 预设: - - + + File Format 文件格式 - - + + Format: 格式: - - + + Output File 输出文件 - - + + Output file path will be generated automatically... 输出文件路径将自动生成... - + Media Files (*.mp4 *.mkv *.avi *.mov *.flv *.wmv *.webm *.ts *.m4v);;All Files (*.*) 媒体文件 (*.mp4 *.mkv *.avi *.mov *.flv *.wmv *.webm *.ts *.m4v);;所有文件 (*.*) - + Save Transcoded File 保存转码文件 - - - - + + + + Transcode / Add to Queue 转码 / 添加到队列 - + Transcoding... 转码中... - + Success 成功 - + File transcoded successfully! 文件转码成功! - + Error 错误 - + Failed to transcode file. 文件转码失败。 - - + + Add to Queue 添加到队列 - + Transcode 转码 - - AIProcessingPage - - Python Required - 需要 Python - - - AI Processing requires Python 3.9 and additional packages. - -Would you like to download and install them now? -(Download size: ~550 MB, completely isolated from system Python) - AI 处理需要 Python 3.9 及其他依赖包。 - -是否现在下载并安装? -(下载大小:约 550 MB,与系统 Python 完全隔离) - - - AI Processing Unavailable - AI 处理不可用 - - - AI Processing features require Python to be installed. - -You can install it later by returning to this page. - AI 处理功能需要安装 Python。 - -您可以稍后返回此页面进行安装。 - - - Input File - 输入文件 - - - Select a media file or click Batch for multiple files... - 选择媒体文件或点击批量处理多个文件... - - - All Files (*.*) - 所有文件 (*.*) - - - Select Media File - 选择媒体文件 - - - Algorithm - 算法 - - - Select Algorithm: - 选择算法: - - - Upscaler - 超分辨率 - - - Algorithm Settings - 算法设置 - - - Upscale Factor: - 放大倍数: - - - Video Settings - 视频设置 - - - Audio Settings - 音频设置 - - - Codec: - 编解码器: - - - Bitrate: - 比特率: - - - File Format - 文件格式 - - - Format: - 格式: - - - Output File - 输出文件 - - - Output file path... - 输出文件路径... - - - Process / Add to Queue - 处理 / 添加到队列 - - - Add to Queue - 添加到队列 - - - Process - 处理 - - - Processing... - 处理中... - - - Success - 成功 - - - AI processing completed successfully! - AI 处理成功完成! - - - Error - 错误 - - - Failed to process file. - 文件处理失败。 - - - Warning - 警告 - - - Please select an input file. - 请选择输入文件。 - - - Please select an output file. - 请选择输出文件。 - - diff --git a/src/transcoder/src/transcoder_bmf.cpp b/src/transcoder/src/transcoder_bmf.cpp index 4bcb1bae..faefa6db 100644 --- a/src/transcoder/src/transcoder_bmf.cpp +++ b/src/transcoder/src/transcoder_bmf.cpp @@ -14,6 +14,7 @@ */ #include "../include/transcoder_bmf.h" +#include "../../common/include/info.h" #include #include @@ -22,6 +23,51 @@ #include #endif +// Helper function to map decoder codec name to encoder name +static std::string map_video_codec_to_encoder(const std::string& codec_name) { + if (codec_name == "h264" || codec_name == "avc") + return "libx264"; + if (codec_name == "hevc" || codec_name == "h265") + return "libx265"; + if (codec_name == "vp8") + return "libvpx"; + if (codec_name == "vp9") + return "libvpx-vp9"; + if (codec_name == "av1") + return "libaom-av1"; + if (codec_name == "mpeg4") + return "mpeg4"; + if (codec_name == "mpeg2video") + return "mpeg2video"; + if (codec_name == "mjpeg") + return "mjpeg"; + if (codec_name == "png") + return "png"; + // Default to libx264 for unknown codecs + return "libx264"; +} + +static std::string map_audio_codec_to_encoder(const std::string& codec_name) { + if (codec_name == "aac") + return "aac"; + if (codec_name == "mp3") + return "libmp3lame"; + if (codec_name == "vorbis") + return "libvorbis"; + if (codec_name == "opus") + return "libopus"; + if (codec_name == "flac") + return "flac"; + if (codec_name == "ac3") + return "ac3"; + if (codec_name == "eac3") + return "eac3"; + if (codec_name.find("pcm_") == 0) + return "pcm_s16le"; + // Default to aac for unknown codecs + return "aac"; +} + /* Receive pointers from converter */ TranscoderBMF::TranscoderBMF(ProcessParameter *process_parameter, EncodeParameter *encode_parameter) @@ -362,12 +408,34 @@ bool TranscoderBMF::prepare_info(std::string input_path, // Build video_params object with only valid parameters nlohmann::json video_params = nlohmann::json::object(); - // Always add codec and bitrate + // Probe input file for codec and pixel format info if needed + std::string input_video_codec; + std::string input_audio_codec; + std::string input_pixel_format; std::string video_codec_name = encode_parameter->get_video_codec_name(); - if (!video_codec_name.empty()) + std::string audio_codec_name = encode_parameter->get_audio_codec_name(); + std::string pixel_format = encode_parameter->get_pixel_format(); + + if (video_codec_name.empty() || audio_codec_name.empty() || pixel_format.empty()) { + // Use Info class to probe input file + Info info; + info.send_info(const_cast(input_path.c_str())); + QuickInfo *quick_info = info.get_quick_info(); + if (quick_info) { + input_video_codec = quick_info->videoCodec; + input_audio_codec = quick_info->audioCodec; + input_pixel_format = quick_info->pixelFormat; + } + } + + // Add video codec - use input codec if not specified (same as input) + if (!video_codec_name.empty()) { video_params["codec"] = video_codec_name; - else - video_params["codec"] = "libx264"; + } else { + std::string encoder = map_video_codec_to_encoder(input_video_codec); + video_params["codec"] = encoder; + BMFLOG(BMF_INFO) << "Using input video codec: " << input_video_codec << " -> encoder: " << encoder; + } video_params["bit_rate"] = encode_parameter->get_video_bit_rate(); // Only add width if it's set (> 0) @@ -388,19 +456,23 @@ bool TranscoderBMF::prepare_info(std::string input_path, video_params["qscale"] = qscale; } - // Only add pixel format if it's set (not empty) - std::string pixel_format = encode_parameter->get_pixel_format(); + // Add pixel format - use input pixel format if not specified (same as input) if (!pixel_format.empty()) { video_params["pixel_format"] = pixel_format; + } else if (!input_pixel_format.empty()) { + video_params["pixel_format"] = input_pixel_format; + BMFLOG(BMF_INFO) << "Using input pixel format: " << input_pixel_format; } // Build audio_params object nlohmann::json audio_params = nlohmann::json::object(); - std::string audio_codec_name = encode_parameter->get_audio_codec_name(); - if (!audio_codec_name.empty()) + if (!audio_codec_name.empty()) { audio_params["codec"] = audio_codec_name; - else - audio_params["codec"] = "aac"; + } else { + std::string encoder = map_audio_codec_to_encoder(input_audio_codec); + audio_params["codec"] = encoder; + BMFLOG(BMF_INFO) << "Using input audio codec: " << input_audio_codec << " -> encoder: " << encoder; + } audio_params["bit_rate"] = encode_parameter->get_audio_bit_rate(); encoder_para = {{"output_path", output_path}, From 28758fc559e78518e71f661f07d3e35f40ec975b Mon Sep 17 00:00:00 2001 From: Jack Lau Date: Fri, 16 Jan 2026 22:11:22 +0800 Subject: [PATCH 2/3] transcoder_bmf: catch unexecpted exit with reminding Signed-off-by: Jack Lau --- src/transcoder/src/transcoder_bmf.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/transcoder/src/transcoder_bmf.cpp b/src/transcoder/src/transcoder_bmf.cpp index faefa6db..ff02d8e2 100644 --- a/src/transcoder/src/transcoder_bmf.cpp +++ b/src/transcoder/src/transcoder_bmf.cpp @@ -588,7 +588,12 @@ bool TranscoderBMF::transcode(std::string input_path, std::string output_path) { nlohmann::json graph_para = {{"dump_graph", 1}}; graph.SetOption(bmf_sdk::JsonParam(graph_para)); - int result = graph.Run(); + int result = -1; + try { + result = graph.Run(); + } catch (const std::exception& e) { + BMFLOG(BMF_ERROR) << "BMF graph execution error: " << e.what(); + } // Clean up allocated memory if (algo_node != nullptr) { From a894d0ecfa641edfaf819aed1aebc7e80d0d84a1 Mon Sep 17 00:00:00 2001 From: Jack Lau Date: Fri, 16 Jan 2026 22:12:26 +0800 Subject: [PATCH 3/3] transcoder_bmf: fix possible buffer overflow Signed-off-by: Jack Lau --- src/transcoder/src/transcoder_bmf.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/transcoder/src/transcoder_bmf.cpp b/src/transcoder/src/transcoder_bmf.cpp index ff02d8e2..44497dee 100644 --- a/src/transcoder/src/transcoder_bmf.cpp +++ b/src/transcoder/src/transcoder_bmf.cpp @@ -23,6 +23,8 @@ #include #endif +#define MAX_STR_SIZE 256 + // Helper function to map decoder codec name to encoder name static std::string map_video_codec_to_encoder(const std::string& codec_name) { if (codec_name == "h264" || codec_name == "avc") @@ -251,7 +253,7 @@ std::string TranscoderBMF::get_python_module_path() { // First check if BMF_MODULE_PATH environment variable is set // This allows runtimes (AppImage, LingLong, Flatpak, etc.) to specify the module path const char* env_module_path = getenv("BMF_MODULE_PATH"); - if (env_module_path && strlen(env_module_path) > 0) { + if (env_module_path && strnlen(env_module_path, MAX_STR_SIZE) > 0) { std::filesystem::path env_path(env_module_path); if (std::filesystem::exists(env_path)) { module_path = env_path.string();