In deze Java-applicatie probeer ik een video om te zetten in kleine clips.

Hier is de implementatieklasse voor hetzelfde

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; } } 

De volledige oplossing is beschikbaar op Github . Ik gebruik eigenlijk CompletableFuture en voer de FFMPEG-opdracht uit door een Java-proces te maken. De tijd die het kost, is te veel. Voor een video van 40 minuten duurt het meer dan 49 minuten op een computer met 64 CPUs. Ik probeer de kerngrootte te verkleinen tot 8 of zoiets, en ook de prestaties te verbeteren, aangezien dit soort prestaties “niet acceptabel zal zijn voor welke toepassing dan ook.

22-jan-2017 update
Eén update, ik heb het FFMPEG-commando gewijzigd om clips te maken en bijgewerkt naar FFMPEG 3, maar er is geen verbetering.

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

Opmerkingen

  • Ik heb enkele voorbeelden gepost met JavaCV Ik heb ‘ niet geprobeerd met een lange video, maar voor korte videos (bijv. 5 minuten) is de verwerkingstijd ongeveer 1 minuut.

Antwoord

Dat is een natuurlijke beperking voor video codering. Op moderne machines wordt 1 minuut 720p-video ongeveer in 1 minuut gecodeerd.

U kunt veel tijd besparen als u niet opnieuw hoeft te coderen (d.w.z. codec- of videoformaat wijzigen) door de optie -codec copy ffmpeg te gebruiken.

Je zei ook dat je 64 cores hebt, maar dat je code slechts 1 thread gebruikt voor codering. Gebruik -threads 0 om ffmpeg zelf te laten kiezen.

Als je dit in Java wilt doen, geef dan Jaffree een kans (ik “ben een auteur).

Reacties

  • Als je Jaffree hebt geschreven, geef dat dan expliciet aan .
  • github.com/bramp/ffmpeg-cli-wrapper is misschien een betere oplossing voor jou.
  • Ik ben Jaffree precies begonnen vanwege verschillende problemen met ffmpeg-cli-wrapper.

Answer

Ik weet dat dit een oude vraag, maar ik denk dat dit nuttig kan zijn voor Java-ontwikkelaars.

Er is een mooie bibliotheek genaamd JavaCV deze live is een wrapper voor meerdere C- en C ++ -bibliotheken zoals FFmpeg.

Dit is een eenvoudig voorbeeld van hoe u een converter kunt implementeren:

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(); } } 

Deze basisimplementatie laat zien hoe u een video converteert met een FFmpeg-pakket of een JavaCV-frame .

Reacties

  • Welkom bij Code Review. Je hebt een alternatieve oplossing gepresenteerd, maar ‘ heb ik de code niet bekeken. Leg alstublieft uw redenering uit (hoe uw oplossing werkt en waarom deze beter is dan het origineel), zodat de auteur en andere lezers kunnen leren van uw denkproces.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *