!7 cmodule VideoSplicer > DynPrintLog { S inputFile, outputFile; S timestamps; transient int audioWindowSize = 16000/10; // 10 per second transient ImageSurface isPreview; transient JAmplitudeGraph graph; visual jvsplit(northAndCenterWithMargins( vstackWithSpacing( withLabel("Input video:", filePathInputWithBrowseButton(dm_textField('inputFile))), withLabel("Output video:", filePathInputWithBrowseButton(dm_textField('outputFile))), rightAlignedLine( jbutton("Load video", rThread loadVideo), jbutton("Make video", rThread makeVideo)), jsection("Audio", jMinHeight(50, graph = setForeground(Color.red, swingNu(JAmplitudeGraph))))), jsection("Timestamps", dm_textArea('timestamps))), jhsplit(jsection("Preview", jscroll_center(isPreview = jImageSurface())), super)); void loadVideo enter { File f = newFile(inputFile); if (!fileExists(f)) ret with infoBox("File not found: " + f2s(f)); S id = md5(f2s(f)); File previewFile = prepareCacheProgramFile("preview-" + id + ".jpg"); File audioFile = prepareCacheProgramFile("preview-" + id + ".wav"); if (!fileExists(previewFile)) { print("Getting preview image..."); ffmpeg_getSingleFrame(f, previewFile, 0.0); print("Done"); } else print("Have preview image"); isPreview.setImageAndZoomToDisplay(loadImage2(previewFile)); if (!fileExists(audioFile)) { print("Extracting audio..."); ffmpeg_toMonoAudio_16k(f, audioFile); print("Done - " + fileInfo(audioFile)); } else print("Have audio"); print("Getting volume profile..."); float[] profile = decodeWAVToMonoSamples_floatVolumeProfile(audioFile, audioWindowSize); print("Have volume profile (" + nEntries(l(profile)) + ")"); //printStruct(takeFirstOfFloatArray(100, profile)); graph.setValues(profile); } void makeVideo enter { L ranges = parseTimestampRanges(timestamps); if (empty(ranges)) ret with infoBox("Need timestamps"); if (fileExists(outputFile) && !confirmOKCancel("Overwrite " + fileName(outputFile) + "?")) ret; temp infoBox_noHide("Cutting video..."); backtick(ffmpegCmd() + " " + ffmpeg_argsForSplice(inputFile, outputFile, timestamps)); infoBox("Done cutting video!" + fileInfo(outputFile)); } }