Skip to content

Commit c09731a

Browse files
Add close project and export options
1 parent 4f6190d commit c09731a

File tree

4 files changed

+75
-12
lines changed

4 files changed

+75
-12
lines changed

Ffmpeg.lua

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ return class.create(function(ffmpeg)
117117
return args
118118
end
119119

120-
function ffmpeg:createCommand(part, filename, options, parameters)
120+
function ffmpeg:createCommand(part, filename, options, sourceOptions, parameters)
121121
--[[
122122
'-ss position (input/output)'
123123
When used as an input option (before -i), seeks in this input file to position.
@@ -138,7 +138,7 @@ return class.create(function(ffmpeg)
138138
]]
139139
local srcOptions = {}
140140
local destOptions = {}
141-
if part.from ~= nil then
141+
if part.from ~= nil and part.from >= 0 then
142142
local delay = (parameters and parameters.seekDelay) or self.seekDelayMs or 0
143143
if (delay >= 0) and (delay < part.from) then
144144
List.concat(srcOptions, '-ss', formatTime(part.from - delay))
@@ -149,15 +149,16 @@ return class.create(function(ffmpeg)
149149
List.concat(destOptions, '-ss', formatTime(part.from))
150150
end
151151
end
152-
if part.to ~= nil then
153-
if part.from ~= nil then
152+
if part.to ~= nil and part.to >= 0 then
153+
if part.from ~= nil and part.to > part.from then
154154
List.concat(destOptions, '-t', formatTime(part.to - part.from))
155155
--List.concat(destOptions, '-to', formatTime(part.to))
156156
else
157157
List.concat(destOptions, '-t', formatTime(part.to))
158158
end
159159
end
160160
List.concat(destOptions, options)
161+
List.concat(srcOptions, sourceOptions)
161162
local sourceFile = self.sources[part.sourceId]
162163
return self:computeArguments(filename, destOptions, sourceFile:getPath(), srcOptions)
163164
end
@@ -175,21 +176,23 @@ return class.create(function(ffmpeg)
175176
end
176177
end
177178

178-
function ffmpeg:createCommands(destFilename, parts, destOptions, parameters)
179+
function ffmpeg:createCommands(destFilename, parts, options, sourceOptions, parameters)
179180
local commands = {}
180181
local filename = destFilename
181182
if parameters.subtitles then
182183
filename = self:createTempFile('full.tmp'):getPath()
183184
end
184-
if #parts == 1 then
185-
table.insert(commands, self:createCommand(parts[1], filename, destOptions, parameters))
185+
if #parts == 0 then
186+
table.insert(commands, self:createCommand({}, filename, options, sourceOptions, parameters))
187+
elseif #parts == 1 then
188+
table.insert(commands, self:createCommand(parts[1], filename, options, sourceOptions, parameters))
186189
elseif #parts > 1 then
187190
local concatScript = StringBuffer:new()
188191
concatScript:append('# fcut')
189192
for i, part in ipairs(parts) do
190193
local partName = 'part_'..tostring(i)..'.tmp'
191194
local outFilename = self:createTempFile(partName):getPath()
192-
table.insert(commands, self:createCommand(part, outFilename, destOptions, parameters))
195+
table.insert(commands, self:createCommand(part, outFilename, options, sourceOptions, parameters))
193196
local concatPartname = string.gsub(outFilename, '[\\+]', '/')
194197
--local concatPartname = partName -- to be safe
195198
concatScript:append('\nfile ', concatPartname)

fcut.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ local httpContexts = {
353353
return false
354354
end,
355355
['export(requestJson)?method=POST&:Content-Type=application/json'] = function(exchange, parameters)
356-
local commands = ffmpeg:createCommands(parameters.filename, parameters.parts, parameters.options or {}, parameters.parameters or {})
356+
local commands = ffmpeg:createCommands(parameters.filename, parameters.parts, parameters.options or {}, parameters.sourceOptions or {}, parameters.parameters or {})
357357
local exportId = strings.formatInteger(system.currentTimeMillis(), 64)
358358
logger:info('export '..exportId..' '..tostring(#commands)..' command(s)')
359359
exportContexts[exportId] = {

htdocs/fcut.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<div class="bar-flex-row">
2424
<button v-on:click="openProject().then(function() { pages.navigateTo('preview'); })" title="Select FCut Project file to open"><i class="fas fa-file"></i></button>
2525
<button v-on:click="saveProject()" title="Select FCut Project file to save as"><i class="fas fa-save"></i></button>
26+
<button v-if="parts.length > 0" v-on:click="closeProject()" title="Close FCut Project"><i class="fas fa-trash"></i></button>
2627
<span class="bar-flex-row-content"></span>
2728
<button v-on:click="pages.navigateTo('help')"><i class="fas fa-question"></i></button>
2829
</div>
@@ -245,6 +246,19 @@ <h2>Export</h2>
245246
<div class="input-bar">
246247
<label><input type="checkbox" v-model="exportMapAllStreams" /> Map all streams</label>
247248
</div>
249+
<div class="input-bar">
250+
<label><input type="checkbox" v-model="exportUseOptions" /> Use additional options</label>
251+
</div>
252+
<template v-if="exportUseOptions">
253+
<div class="bar-flex-row">
254+
<label>Source:</label>
255+
<input v-model="exportSourceOptions" name="exportSourceOptions" type="text" class="bar-flex-row-content"></input>
256+
</div>
257+
<div class="bar-flex-row">
258+
<label>Destination:</label>
259+
<input v-model="exportOptions" name="exportOptions" type="text" class="bar-flex-row-content"></input>
260+
</div>
261+
</template>
248262
<!--
249263
<div class="input-bar">
250264
<label>Subtitles:</label>

htdocs/fcut.js

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ function updatePart(part) {
1818
}
1919
return part;
2020
}
21+
function parseSourceDuration(duration) {
22+
return Math.floor(parseFloat(duration) - 1.1);
23+
}
2124

2225
var vm = new Vue({
2326
el: '#app',
@@ -33,7 +36,7 @@ var vm = new Vue({
3336
time: true,
3437
cut: true,
3538
bsearch: true,
36-
project: false
39+
project: true
3740
},
3841
step: 1,
3942
period: 180,
@@ -45,6 +48,9 @@ var vm = new Vue({
4548
exportAudioCodec: 'copy',
4649
exportSubtitleCodec: '-',
4750
exportMapAllStreams: true,
51+
exportUseOptions: false,
52+
exportOptions: '',
53+
exportSourceOptions: '',
4854
duration: 0,
4955
parts: [],
5056
partIndex: 0,
@@ -181,7 +187,7 @@ var vm = new Vue({
181187
},
182188
addSource: function(sourceId, beforeIndex) {
183189
var info = this.sources[sourceId];
184-
var duration = Math.floor(parseFloat(info.format.duration) - 1.1);
190+
var duration = parseSourceDuration(info.format.duration);
185191
var part = updatePart({
186192
sourceId: sourceId,
187193
duration: duration,
@@ -432,6 +438,14 @@ var vm = new Vue({
432438
return;
433439
}
434440
var options = [];
441+
if (this.exportUseOptions) {
442+
if (this.exportOptions) {
443+
options = options.concat(this.exportOptions.split(' '));
444+
}
445+
if (this.exportSourceOptions) {
446+
options = options.concat(this.exportSourceOptions.split(' '));
447+
}
448+
}
435449
if (this.exportMapAllStreams) {
436450
options.push('-map', '0');
437451
}
@@ -453,9 +467,26 @@ var vm = new Vue({
453467
} else if (this.exportSubtitleCodec !== '') {
454468
options.push('-scodec', this.exportSubtitleCodec);
455469
}
470+
var parts = [];
471+
for (var i = 0; i < this.parts.length; i++) {
472+
var part = this.parts[i];
473+
var sourceId = part.sourceId;
474+
var info = this.sources[sourceId];
475+
if (info) {
476+
var duration = parseSourceDuration(info.format.duration);
477+
var p = {sourceId: sourceId};
478+
if (part.from > 0) {
479+
p.from = part.from;
480+
}
481+
if (part.to > 0 && part.to < duration) {
482+
p.to = part.to;
483+
}
484+
parts.push(p);
485+
}
486+
}
456487
var request = {
457488
filename: this.destinationFilename,
458-
parts: this.parts,
489+
parts: parts,
459490
options: options
460491
};
461492
this.logBuffer = '';
@@ -542,6 +573,21 @@ var vm = new Vue({
542573
});
543574
});
544575
},
576+
closeProject: function() {
577+
this.sources = [];
578+
this.parts = [];
579+
this.previewSrc = 'roll.png';
580+
this.partIndex = 0;
581+
this.partTime = 0;
582+
this.partEndTime = 0;
583+
this.partInfo = {};
584+
this.canJoin = false;
585+
this.time = 0;
586+
this.destinationFilename = DEFAULT_DESTINATION_FILENAME;
587+
this.projectFilename = DEFAULT_PROJECT_FILENAME;
588+
this.aspectRatio = 0;
589+
this.refreshParts();
590+
},
545591
openProject: function() {
546592
var that = this;
547593
return this.selectFiles(false, false, '.json').then(function(filename) {

0 commit comments

Comments
 (0)