Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

146
LINES

< > BotCompany Repo | #1024630 // AutoJumpCut Batch Mode (Concatenate All Videos)

JavaX source code (Dynamic Module) [tags: use-pretranspiled] - run with: Stefan's OS

Libraryless. Click here for Pure Java version (21298L/156K).

1  
!7
2  
3  
sclass VidFile {
4  
  File file;
5  
  double length = -1;
6  
  
7  
  transient float[] profile;
8  
  transient L<DoubleRange> ranges;
9  
10  
  S id() { ret md5FromFilePathSizeAndDate(file); }
11  
  File audioFile() { ret prepareCacheProgramFile("preview-" + id() + ".wav"); }
12  
}
13  
14  
module AJCBatch > DynObjectTable<VidFile> {
15  
  S outputFile;
16  
  int volumeThresholdPercent = 15;
17  
  S minSilence = "0.2", leadIn = "0.2", leadOut = "0.2";
18  
  transient double profileSamplingInterval = 0.05; // 50 ms
19  
  transient int audioWindowSize = iround(profileSamplingInterval*16000);
20  
  S originalLength, cutLength;
21  
  
22  
  transient ReliableSingleThread rstScan = dm_rst(this, r scan);
23  
  
24  
  visualize {
25  
    JComponent sup = super.visualize();
26  
    ret centerAndSouthWithMargins(
27  
      jHandleMultiFileDrop(vf<L<File>> onFileDrop,
28  
        withCenteredTitle("Input videos to jump-cut & concatenate (you can drag&drop files here):",
29  
        withRightAlignedButtons(sup,
30  
          tableDependentButton(table, "Move up", r moveUp),
31  
          tableDependentButton(table, "Move down", r moveDown),
32  
          tableDependentButton(table, "Remove selected", r removeSelected)
33  
        ))),
34  
      vstackWithSpacing(
35  
        centeredLine(withLabel("Total input duration:", dm_boldLabel('originalLength))),
36  
        dm_ajc_parametersSection(),
37  
        centeredLine(withLabel("Total output duration (est.):", dm_boldLabel('cutLength))),
38  
        withLabel("Output video:", filePathInputWithBrowseButton(dm_textField('outputFile))),
39  
        rightAlignedLine(fontSizePlus(3, jbutton("Make video", rThread makeVideo))),
40  
        ffmpegVersionPanel()
41  
      ));
42  
  }
43  
  
44  
  void onFileDrop(L<File> files) enter {
45  
    print("Have file drop");
46  
    Set<File> haveFiles = collectAsSet file(data());
47  
    addAll(map(listMinusSet(files, haveFiles), f -> nu VidFile(file := f)));
48  
    rstScan.trigger();
49  
  }
50  
  
51  
  start {
52  
    itemToMap = func(VidFile v) -> Map {
53  
      litorderedmap(
54  
        "Video" := fileName(v.file),
55  
        "Folder" := dirPath(v.file),
56  
        "Duration" := !fileExists(v.file) ? "File not found"
57  
          : v.length < 0 ? "[calculating]" : formatMinuteAndSeconds(iceil(v.length))
58  
      )
59  
    };
60  
    rstScan.trigger();
61  
    dm_watchFields(allNonStaticNonTransientFields(AJCParameters), r recut);
62  
  }
63  
  
64  
  void recut {
65  
    for (VidFile v : clonedList())
66  
      v.ranges = null;
67  
    rstScan.trigger();
68  
  }
69  
  
70  
  void scan {
71  
    bool change;
72  
    double lenIn = 0, lenOut = 0;
73  
    for (VidFile v : clonedList()) pcall {
74  
      if (v.ranges == null || v.length < 0 && fileExists(v.file)) {
75  
        File audio = v.audioFile();
76  
        if (fileLength(audio) == 0) {
77  
          print("Extracting audio from " + v.file);
78  
          ffmpeg_toMonoAudio_16k(v.file, audio); // TODO: temp file for safety?
79  
          v.profile = null;
80  
        }
81  
        if (v.profile == null)
82  
          v.profile = decodeWAVToMonoSamples_floatVolumeProfile(audio, audioWindowSize);
83  
        v.length = l(v.profile)*profileSamplingInterval;
84  
        v.ranges = ajc_findSpeechPartsFromVolumeProfile(v.profile,
85  
          shallowCloneToClass AJCParameters(module()));
86  
87  
        set change;
88  
      }
89  
      
90  
      lenIn += v.length;
91  
      lenOut += totalLengthOfDoubleRanges(v.ranges);
92  
    }
93  
    setField(originalLength := formatMinuteAndSeconds(iceil(lenIn));
94  
    setField(cutLength := formatMinuteAndSeconds(iceil(lenOut));
95  
    if (change) fireDataChanged();
96  
  }
97  
  
98  
  void makeVideo {
99  
    temp dm_tempDisableAllButtons();
100  
    
101  
    while (rstScan.running()) sleep(10);
102  
    
103  
    if (emptyAfterTrim(outputFile)) ret with infoBox("Need output file path");
104  
    File out = newFile(trim(outputFile));
105  
    
106  
    L<VidFile> l = clonedList();
107  
    if (empty(l)) ret with infoBox("No input files");
108  
    
109  
    if (fileExists(out) && !confirmOKCancel("Overwrite " + fileName(out) + "?")) ret;
110  
    
111  
    L<File> files = collect file(l);
112  
    LL<DoubleRange> ranges = collect ranges(l);
113  
    
114  
    temp tempInfoBox_noHide("Splicing video...");
115  
    backtickToConsole(ffmpegCmd() + " -y " + ffmpeg_argsForSplice_multipleInputVideos(files, out, ranges));
116  
    
117  
    if (fileExists(out))
118  
      infoBox("Done splicing video!"  + fileInfo(out));
119  
    else
120  
      infoBox("Something went wrong...");
121  
  }
122  
  
123  
  void moveUp {
124  
    L<Int> indices = selectedIndices();
125  
    int i = first(indices), j = last(indices)+1;
126  
    if (i <= 0) ret;
127  
    VidFile v = data.get(i-1);
128  
    remove(v);
129  
    add(j-1, v);
130  
    new L<Int> sel;
131  
    for (int k = i; k < j; k++) sel.add(k-1);
132  
    selectTableRows(table, asIntArray(sel));
133  
  }
134  
  
135  
  void moveDown {
136  
    L<Int> indices = selectedIndices();
137  
    int i = first(indices), j = last(indices)+1;
138  
    if (j >= l(data)) ret;
139  
    VidFile v = data.get(j);
140  
    remove(v);
141  
    add(i, v);
142  
    new L<Int> sel;
143  
    for (int k = i; k < j; k++) sel.add(k+1);
144  
    selectTableRows(table, asIntArray(sel));
145  
  }
146  
}

download  show line numbers  debug dex  old transpilations   

Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv

No comments. add comment

Snippet ID: #1024630
Snippet name: AutoJumpCut Batch Mode (Concatenate All Videos)
Eternal ID of this version: #1024630/45
Text MD5: c3fc75f21c48259711760d8b14b08d4a
Transpilation MD5: f3e6d307b30ad6c941ade157a29ebd57
Author: stefan
Category: javax / ajc
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2020-01-09 22:25:25
Source code size: 4932 bytes / 146 lines
Pitched / IR pitched: No / No
Views / Downloads: 272 / 1093
Version history: 44 change(s)
Referenced in: [show references]