1
0
mirror of https://github.com/mifi/lossless-cut.git synced 2024-11-21 18:02:35 +01:00

Allow for testing keyframe cut

This means a button for toggling whether -ss should be before -i or after (default)
See discussion #13 and #79
Also some text/button enchancements
This commit is contained in:
Mikael Finstad 2018-09-09 20:50:21 +02:00
parent 197c2f9418
commit 31c8b86e50
2 changed files with 38 additions and 19 deletions

View File

@ -57,7 +57,7 @@ function handleProgress(process, cutDuration, onProgress) {
async function cut({
customOutDir, filePath, format, cutFrom, cutTo, cutToApparent, videoDuration, rotation,
includeAllStreams, onProgress, stripAudio,
includeAllStreams, onProgress, stripAudio, keyframeCut,
}) {
const ext = path.extname(filePath) || `.${format}`;
const cutSpecification = `${util.formatDuration(cutFrom, true)}-${util.formatDuration(cutToApparent, true)}`;
@ -72,18 +72,32 @@ async function cut({
const cutFromArgs = cutFrom === 0 ? [] : ['-ss', cutFrom];
const cutToArgs = cutTo === undefined || cutTo === videoDuration ? [] : ['-t', cutDuration];
const inputCutArgs = keyframeCut ? [
...cutFromArgs,
'-i', filePath,
...cutToArgs,
'-avoid_negative_ts', 'make_zero',
] : [
'-i', filePath,
...cutFromArgs,
...cutToArgs,
];
const rotationArgs = rotation !== undefined ? ['-metadata:s:v:0', `rotate=${rotation}`] : [];
const ffmpegArgs = [
'-i', filePath, '-y',
...inputCutArgs,
...(stripAudio ? ['-an'] : ['-acodec', 'copy']),
'-vcodec', 'copy',
'-scodec', 'copy',
...cutFromArgs, ...cutToArgs,
...(includeAllStreams ? ['-map', '0'] : []),
'-map_metadata', '0',
...rotationArgs,
'-f', format,
outPath,
'-f', format, '-y', outPath,
];
console.log('ffmpeg', ffmpegArgs.join(' '));
@ -108,8 +122,7 @@ async function html5ify(filePath, outPath, encodeVideo) {
const ffmpegArgs = [
'-i', filePath, ...videoArgs, '-an',
'-y',
outPath,
'-y', outPath,
];
console.log('ffmpeg', ffmpegArgs.join(' '));

View File

@ -103,6 +103,7 @@ class App extends React.Component {
includeAllStreams: false,
captureFormat: 'jpeg',
customOutDir: undefined,
keyframeCut: false,
};
this.state = {
@ -316,15 +317,12 @@ class App extends React.Component {
async cutClick() {
if (this.state.working) return alert('I\'m busy');
const cutStartTime = this.state.cutStartTime;
const cutEndTime = this.state.cutEndTime;
const filePath = this.state.filePath;
const outputDir = this.state.customOutDir;
const fileFormat = this.state.fileFormat;
const videoDuration = this.state.duration;
const {
cutStartTime, cutEndTime, filePath, customOutDir, fileFormat, duration, includeAllStreams,
stripAudio, keyframeCut,
} = this.state;
const rotation = this.isRotationSet() ? this.getRotation() : undefined;
const includeAllStreams = this.state.includeAllStreams;
const stripAudio = this.state.stripAudio;
if (!this.isCutRangeValid()) {
return alert('Start time must be before end time');
@ -333,16 +331,17 @@ class App extends React.Component {
this.setState({ working: true });
try {
return await ffmpeg.cut({
customOutDir: outputDir,
customOutDir,
filePath,
format: fileFormat,
cutFrom: cutStartTime,
cutTo: cutEndTime,
cutToApparent: this.getApparentCutEndTime(),
videoDuration,
videoDuration: duration,
rotation,
includeAllStreams,
stripAudio,
keyframeCut,
onProgress: progress => this.onCutProgress(progress),
});
} catch (err) {
@ -547,6 +546,13 @@ class App extends React.Component {
</div>
<div className="right-menu">
<button
title={`Cut mode ${this.state.keyframeCut ? 'nearest keyframe cut' : 'normal cut'}`}
onClick={withBlur(() => this.setState({ keyframeCut: !this.state.keyframeCut }))}
>
{this.state.keyframeCut ? 'kc' : 'nc'}
</button>
<button
title={`Set output streams. Current: ${this.state.includeAllStreams ? 'include (and cut) all streams' : 'include only primary streams'}`}
onClick={withBlur(() => this.toggleIncludeAllStreams())}
@ -555,7 +561,7 @@ class App extends React.Component {
</button>
<button
title={`Delete audio? Current: ${this.state.stripAudio ? 'delete audio tracks' : "don't delete audio tracks"}`}
title={`Delete audio? Current: ${this.state.stripAudio ? 'delete audio tracks' : 'keep audio tracks'}`}
onClick={withBlur(() => this.setState({ stripAudio: !this.state.stripAudio }))}
>
{this.state.stripAudio ? 'da' : 'ka'}
@ -572,7 +578,7 @@ class App extends React.Component {
title={`Custom output dir (cancel to restore default). Current: ${this.getOutputDir() || 'Not set (use input dir)'}`}
onClick={withBlur(() => this.setOutputDir())}
>
{this.getOutputDir() ? `...${this.getOutputDir().substr(-10)}` : 'OUTDIR'}
{this.getOutputDir() ? 'cd' : 'id'}
</button>
<i