I denne java-applikation prøver jeg at konvertere en video til små klip.

Her er implementeringsklassen for den samme

package ffmpeg.clip.process; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Paths; import java.time.Duration; import java.time.LocalTime; import java.time.temporal.ChronoUnit; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import ffmpeg.clip.utils.VideoConstant; import ffmpeg.clip.utils.VideoUtils; /* * @author Nitishkumar Singh * @Description: class will use ffmpeg to break an source video into clips */ public class VideoToClip { /* * Prevent from creating instance */ private VideoToClip() { } /** * Get Video Duration is milliseconds * * @Exception IOException - File does not exist VideoException- Video File have data issues */ static LocalTime getDuration(String sourceVideoFile) throws Exception { if (!Paths.get(sourceVideoFile).toFile().exists()) throw new Exception("File does not exist!!"); Process proc = new ProcessBuilder(VideoConstant.SHELL, VideoConstant.SHELL_COMMAND_STRING_ARGUMENT, String.format(VideoConstant.DURATION_COMMAND, sourceVideoFile)).start(); boolean errorOccured = (new BufferedReader(new InputStreamReader(proc.getErrorStream())).lines() .count() > VideoConstant.ZERO); String durationInSeconds = new BufferedReader(new InputStreamReader(proc.getInputStream())).lines() .collect(Collectors.joining(System.lineSeparator())); proc.destroy(); if (errorOccured || (durationInSeconds.length() == VideoConstant.ZERO)) throw new Exception("Video File have some issues!"); else return VideoUtils.parseHourMinuteSecondMillisecondFormat(durationInSeconds); } /** * Create Clips for Video Using Start and End Second * * @Exception IOException - Clip Creation Process Failed InterruptedException - Clip Creation task get"s failed */ static String toClipProcess(String sourceVideo, String outputDirectory, LocalTime start, LocalTime end, String fileExtension) throws IOException, InterruptedException, ExecutionException { String clipName = String.format(VideoConstant.CLIP_FILE_NAME, VideoUtils.getHourMinuteSecondMillisecondFormat(start), VideoUtils.getHourMinuteSecondMillisecondFormat(end), fileExtension); String command = String.format(VideoConstant.FFMPEG_OUTPUT_COMMAND, sourceVideo, VideoUtils.getHourMinuteSecondMillisecondFormat(start), VideoUtils.getHourMinuteSecondMillisecondFormat(end.minus(start.toNanoOfDay(), ChronoUnit.NANOS)), outputDirectory, clipName); LocalTime startTime = LocalTime.now(); System.out.println("Clip Name: " + clipName); System.out.println("FFMPEG Process Execution Started"); CompletableFuture<Process> completableFuture = CompletableFuture.supplyAsync(() -> { try { return executeProcess(command); } catch (InterruptedException | IOException ex) { throw new RuntimeException(ex); } }); completableFuture.get(); // remove LocalTime endTime = LocalTime.now(); System.out.println("Clip Name: " + clipName); System.out.println("FFMPEG Process Execution Finished"); System.out.println("Duration: " + Duration.between(startTime, endTime).toMillis() / 1000); return clipName; } /** * Create and Execute Process for each command */ static Process executeProcess(String command) throws InterruptedException, IOException { Process clipProcess = Runtime.getRuntime().exec(command); clipProcess.waitFor(); return clipProcess; } } 

Hele løsningen findes på Github . Jeg bruger faktisk CompletableFuture og kører FFMPEG-kommando ved at oprette Java Process. Den tid det tager er for meget. For en 40 minutters video tager det mere end 49 minutter på en 64 CPU-maskine. Jeg forsøger at reducere kernestørrelsen til 8 eller noget, samt forbedre dens ydeevne, da denne form for ydeevne ikke vil være acceptabel for enhver form for applikation.

22. januar 2017 opdatering
Én opdatering, jeg har ændret FFMPEG-kommandoen for at oprette klip og opdateret til FFMPEG 3, men der er ingen forbedring.

ffmpeg -y -i INPUT_FILE_PATH -ss TIME_STAMP -t DURATION_TO_CLIP OUTPUT_FILE_PATH

Kommentarer

  • Jeg sendte nogle eksempler ved hjælp af JavaCV, jeg gjorde ikke ‘ t prøvet med en lang videovideo, men til korte videoer (dvs. 5 minutter) behandlingstiden er ca. 1 minut.

Svar

Det er en naturlig begrænsning af video kodning. På moderne maskiner kodes 1 minut 720p video cirka på 1 minut.

Du kan spare meget tid, hvis du ikke har brug for omkodning (dvs. ændre codec eller videostørrelse) ved hjælp af -codec copy ffmpeg option.

Du sagde også, at du har 64 kerner, men din kode bruger kun 1 tråd til kodning. Brug -threads 0 for at tillade ffmpeg at vælge selv.

Også hvis du har brug for at udføre dette i Java – giv Jaffree en chance (jeg er en forfatter).

Kommentarer

  • Hvis du skrev Jaffree, bedes du angive det eksplicit .
  • github.com/bramp/ffmpeg-cli-wrapper kan være en bedre løsning for dig.
  • Jeg startede Jaffree nøjagtigt på grund af flere problemer med ffmpeg-cli-wrapper.

Svar

Jeg ved, det er et gammelt spørgsmål, men jeg tror, det kan være nyttigt for Java-udviklere.

Der er et dejligt bibliotek kaldet JavaCV, dette live er en indpakning til flere C- og C ++ -biblioteker som FFmpeg.

Dette er et simpelt eksempel på, hvordan man implementerer en konverter:

import org.bytedeco.javacpp.avcodec; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; public class PacketRecorderTest { private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd__hhmmSSS"); private static final int RECORD_LENGTH = 5000; private static final boolean AUDIO_ENABLED = false; public static void main(String[] args) throws FrameRecorder.Exception, FrameGrabber.Exception { String inputFile = "/home/usr/videos/VIDEO_FILE_NAME.mp4"; // Decodes-encodes String outputFile = "/tmp/" + DATE_FORMAT.format(new Date()) + "_frameRecord.mp4"; PacketRecorderTest.frameRecord(inputFile, outputFile); // copies codec (no need to re-encode) outputFile = "/tmp/" + DATE_FORMAT.format(new Date()) + "_packetRecord.mp4"; PacketRecorderTest.packetRecord(inputFile, outputFile); } public static void frameRecord(String inputFile, String outputFile) throws FrameGrabber.Exception, FrameRecorder.Exception { int audioChannel = AUDIO_ENABLED ? 1 : 0; FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile); FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 1280, 720, audioChannel); grabber.start(); recorder.start(); Frame frame; long t1 = System.currentTimeMillis(); while ((frame = grabber.grabFrame(AUDIO_ENABLED, true, true, false)) != null) { recorder.record(frame); if ((System.currentTimeMillis() - t1) > RECORD_LENGTH) { break; } } recorder.stop(); grabber.stop(); } public static void packetRecord(String inputFile, String outputFile) throws FrameGrabber.Exception, FrameRecorder.Exception { int audioChannel = AUDIO_ENABLED ? 1 : 0; FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile); FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 1280, 720, audioChannel); grabber.start(); recorder.start(grabber.getFormatContext()); avcodec.AVPacket packet; long t1 = System.currentTimeMillis(); while ((packet = grabber.grabPacket()) != null) { recorder.recordPacket(packet); if ((System.currentTimeMillis() - t1) > RECORD_LENGTH) { break; } } recorder.stop(); grabber.stop(); } } 

Denne grundlæggende implementering viser, hvordan man konverterer en video ved hjælp af en FFmpeg-pakke eller en JavaCV-ramme .

Kommentarer

  • Velkommen til Code Review. Du har præsenteret en alternativ løsning, men har ikke ‘ ikke gennemgået koden. Forklar din begrundelse (hvordan din løsning fungerer, og hvorfor den er bedre end originalen), så forfatteren og andre læsere kan lære af din tankeproces.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *