+
-
{t('Create chapters from merged segments? (slow)')}
@@ -171,14 +177,15 @@ const ExportConfirm = memo(({
)}
- {t('Depending on your specific file/player, you may have to try different options for best results.')}
+ {t('Depending on your specific file/player, you may have to try different options for best results.')}
-
+
diff --git a/src/StreamsSelector.jsx b/src/StreamsSelector.jsx
index dded721b..e3d46ff0 100644
--- a/src/StreamsSelector.jsx
+++ b/src/StreamsSelector.jsx
@@ -1,6 +1,6 @@
import React, { memo, useState, useMemo, useCallback } from 'react';
-import { FaCheckCircle, FaPaperclip, FaVideo, FaVideoSlash, FaFileImport, FaVolumeUp, FaVolumeMute, FaBan, FaFileExport } from 'react-icons/fa';
+import { FaImage, FaCheckCircle, FaPaperclip, FaVideo, FaVideoSlash, FaFileImport, FaVolumeUp, FaVolumeMute, FaBan, FaFileExport } from 'react-icons/fa';
import { GoFileBinary } from 'react-icons/go';
import { FiEdit, FiCheck, FiTrash } from 'react-icons/fi';
import { MdSubtitles } from 'react-icons/md';
@@ -13,7 +13,7 @@ import { askForMetadataKey, showJson5Dialog } from './dialogs';
import { formatDuration } from './util/duration';
import { getStreamFps } from './ffmpeg';
import { deleteDispositionValue } from './util';
-import { getActiveDisposition } from './util/streams';
+import { getActiveDisposition, attachedPicDisposition } from './util/streams';
const activeColor = '#429777';
@@ -197,8 +197,13 @@ const Stream = memo(({ dispositionByStreamId, setDispositionByStreamId, filePath
Icon = copyStream ? FaVolumeUp : FaVolumeMute;
codecTypeHuman = t('audio');
} else if (stream.codec_type === 'video') {
- Icon = copyStream ? FaVideo : FaVideoSlash;
- codecTypeHuman = t('video');
+ if (effectiveDisposition === attachedPicDisposition) {
+ Icon = copyStream ? FaImage : FaBan;
+ codecTypeHuman = t('thumbnail');
+ } else {
+ Icon = copyStream ? FaVideo : FaVideoSlash;
+ codecTypeHuman = t('video');
+ }
} else if (stream.codec_type === 'subtitle') {
Icon = copyStream ? MdSubtitles : FaBan;
codecTypeHuman = t('subtitle');
diff --git a/src/hooks/useFfmpegOperations.js b/src/hooks/useFfmpegOperations.js
index e9b01758..b3f36043 100644
--- a/src/hooks/useFfmpegOperations.js
+++ b/src/hooks/useFfmpegOperations.js
@@ -402,7 +402,7 @@ function useFfmpegOperations({ filePath, enableTransferTimestamps }) {
if (!needsSmartCut) await checkOverwrite(smartCutMainPartOutPath);
- // for smart cut we need to use keyframe cut here
+ // for smart cut we need to use keyframe cut here, and no avoid_negative_ts
await cutSingle({
cutFrom: encodeCutTo, cutTo, chaptersPath, outPath: smartCutMainPartOutPath, copyFileStreams: copyFileStreamsFiltered, keyframeCut: true, avoidNegativeTs: false, videoDuration, rotation, allFilesMeta, outFormat, appendFfmpegCommandLog, shortestFlag, ffmpegExperimental, preserveMovData, movFastStart, customTagsByFile, customTagsByStreamId, dispositionByStreamId, videoTimebase, onProgress: onCutProgress,
});
diff --git a/src/util/streams.js b/src/util/streams.js
index 7ac94dea..e386f8b0 100644
--- a/src/util/streams.js
+++ b/src/util/streams.js
@@ -207,8 +207,10 @@ export function shouldCopyStreamByDefault(stream) {
return true;
}
+export const attachedPicDisposition = 'attached_pic';
+
export function isStreamThumbnail(stream) {
- return stream && stream.disposition && stream.disposition.attached_pic === 1;
+ return stream && stream.codec_type === 'video' && stream.disposition?.[attachedPicDisposition] === 1;
}
export const getAudioStreams = (streams) => streams.filter(stream => stream.codec_type === 'audio');