
Recherche avancée
Médias (3)
-
The Slip - Artworks
26 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Texte
-
Podcasting Legal guide
16 mai 2011, par
Mis à jour : Mai 2011
Langue : English
Type : Texte
-
Creativecommons informational flyer
16 mai 2011, par
Mis à jour : Juillet 2013
Langue : English
Type : Texte
Autres articles (45)
-
Gestion générale des documents
13 mai 2011, parMédiaSPIP ne modifie jamais le document original mis en ligne.
Pour chaque document mis en ligne il effectue deux opérations successives : la création d’une version supplémentaire qui peut être facilement consultée en ligne tout en laissant l’original téléchargeable dans le cas où le document original ne peut être lu dans un navigateur Internet ; la récupération des métadonnées du document original pour illustrer textuellement le fichier ;
Les tableaux ci-dessous expliquent ce que peut faire MédiaSPIP (...) -
Publier sur MédiaSpip
13 juin 2013Puis-je poster des contenus à partir d’une tablette Ipad ?
Oui, si votre Médiaspip installé est à la version 0.2 ou supérieure. Contacter au besoin l’administrateur de votre MédiaSpip pour le savoir -
Des sites réalisés avec MediaSPIP
2 mai 2011, parCette page présente quelques-uns des sites fonctionnant sous MediaSPIP.
Vous pouvez bien entendu ajouter le votre grâce au formulaire en bas de page.
Sur d’autres sites (6107)
-
MOV to ACVHD conversion via Spring Boot and FFmpeg leads to file system error
31 décembre 2024, par epicUsernameI am experiencing an issue on a personal project that seeks to convert HEIC to JPG files and MOV files to AVCHD format. The HEIC to JPG conversion works, but the MOV to AVCHD does not, which is where my problems lie.


The intent is to do this with Spring Boot and FFmpeg, using a simple interface done in WindowBuilder.


The relevant bits are the pom file :


<dependencies>
 
 
 <dependency>
 <groupid>jmagick</groupid>
 <artifactid>jmagick</artifactid>
 <version>6.6.9</version>
 </dependency>

 
 <dependency>
 <groupid>net.java.dev.jna</groupid>
 <artifactid>jna</artifactid>
 <version>5.7.0</version> 
 </dependency>
 <dependency>
 <groupid>net.java.dev.jna</groupid>
 <artifactid>jna-platform</artifactid>
 <version>5.7.0</version>
 </dependency>
 
 


 <dependency>
 <groupid>org.bytedeco</groupid>
 <artifactid>ffmpeg</artifactid>
 <version>7.1-1.5.11</version>
 </dependency>
 <dependency>
 <groupid>org.bytedeco</groupid>
 <artifactid>javacv</artifactid>
 <version>1.5.11</version>
 </dependency>
 <dependency>
 <groupid>org.bytedeco</groupid>
 <artifactid>ffmpeg-platform</artifactid>
 <version>7.1-1.5.11</version>
 </dependency>
 
 <dependency>
 <groupid>org.bytedeco</groupid>
 <artifactid>javacpp</artifactid>
 <version>1.5.11</version>
 </dependency>
 </dependencies>




and the main file with the event handling for the application, based on the interface :


package home.multimeida.mmconverter;

imports...

public class MMConverterInterface extends JFrame {

 public static void main(String[] args) {
 
 
 try {
 System.setProperty("jna.library.path", "absolute/path/to/gstreamer/bin");
 // Gst.init("GStreamer Test");
 System.out.println("GStreamer initialized successfully.");
 } catch (Exception e) {
 e.printStackTrace();
 System.out.println("Failed to initialize GStreamer.");
 }
 EventQueue.invokeLater(new Runnable() {
 public void run() {
 try {
 MMConverterInterface frame = new MMConverterInterface();
 frame.setVisible(true);
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
 });
 }

 /**
 * Create the frame.
 */
 public MMConverterInterface() {
 
 // convert button
 
 btnConvert.addActionListener(e -> {
 
 try {
 
 if (sourceFileLabel.getText().equals("No file chosen...") || destinationFolderLabel.getText().equals("No folder selected...")) {
 JOptionPane.showMessageDialog(null, "Please select both an input file and a save location.", "Validation Error", JOptionPane.WARNING_MESSAGE);
 return;
 }
 
 File sourceFile = new File(sourceFileLabel.getText());
 File destinationFile;
 
 if (rdbtnNewRadioButton.isSelected()) {
 
 System.out.println("Converting HEIC to JPG...");
 
 String outputFileName = sourceFile.getName().replaceFirst("[.][^.]+$", ".jpg");
 
 // Call your conversion logic here
 
 destinationFile = new File(destinationFolderLabel.getText(), outputFileName);
 
 convertHeicToJpg(sourceFile, destinationFile);
 
 } else if (rdbtnNewRadioButton_1.isSelected()) {
 
 if (sourceFileLabel.getText().equals("No file chosen...") || destinationFolderLabel.getText().equals("No folder selected...")) {
 JOptionPane.showMessageDialog(null, "Please select both an input file and a save location.", "Validation Error", JOptionPane.WARNING_MESSAGE);
 return;
 }
 
 // Validate source file
 if (!sourceFile.exists() || !sourceFile.canRead()) {
 JOptionPane.showMessageDialog(null, "Source file does not exist or is not readable.", "File Error", JOptionPane.ERROR_MESSAGE);
 return;
 }
 
 // Validate destination folder
 String destinationPath = destinationFolderLabel.getText();
 if (destinationPath == null || destinationPath.isEmpty() || !(new File(destinationPath).isDirectory())) {
 JOptionPane.showMessageDialog(null, "Invalid destination folder.", "File Error", JOptionPane.ERROR_MESSAGE);
 return;
 }
 
 System.out.println("Converting MOV to AVCHD...");
 
 String currentDate = new SimpleDateFormat("yyyyMMdd").format(new Date());

 // Extract the file name without the extension
 String baseName = sourceFile.getName().replaceFirst("[.][^.]+$", "");

 // Sanitize the base name (replace invalid characters with '_')
 baseName = baseName.replaceAll("[^a-zA-Z0-9-_]", "_");
 
 String sanitizedFileName = baseName + "_" + currentDate;
 sanitizedFileName = sanitizedFileName.replaceAll("[^a-zA-Z0-9._-]", "_"); // Allow alphanumeric, '-', '_', and '.'

 destinationFile = new File(destinationPath, sanitizedFileName);
 
 
 /*
 // Ensure the destination file is writable
 if (!destinationFile.canWrite()) {
 JOptionPane.showMessageDialog(null, "Output file is not writable.", "File Error", JOptionPane.ERROR_MESSAGE);
 return;
 }
 */
 

 convertMovToAvchd(sourceFile, destinationFile);
 
 } else {
 
 JOptionPane.showMessageDialog(null, "Please select a conversion type.");
 
 }
 
 } catch (Exception ex) {
 
 JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage(), "Conversion Error", JOptionPane.ERROR_MESSAGE);
 ex.printStackTrace();
 }
 
 
 });
 
 // cancel button:
 
 btnCancel.addActionListener(e -> {
 System.out.println("Operation canceled.");
 System.exit(0); // Close the application
 });

 }
 
 public void convertMovToAvchd(File sourceFile, File destinationFile) {
 avutil.av_log_set_level(avutil.AV_LOG_DEBUG);
 
 

 AVFormatContext inputFormatContext = null;
 AVFormatContext outputFormatContext = new AVFormatContext(null);
 AVCodecContext inputCodecContext = null;
 AVCodecContext outputCodecContext = null;

 try {
 // Validate input file
 if (!sourceFile.exists() || !sourceFile.canRead()) {
 System.out.println("Source file does not exist or is not readable: " + sourceFile.getAbsolutePath());
 return;
 }
 
 // Validate output file path using the validateFileCreation method
 if (!validateFileCreation(destinationFile)) {
 return; // Exit if destination file validation fails
 }

 // Validate output file path
 if (destinationFile.getParentFile() == null || !destinationFile.getParentFile().exists()) {
 System.out.println("Output directory does not exist: " + destinationFile.getParentFile());
 return;
 }
 if (!destinationFile.getParentFile().canWrite()) {
 System.out.println("Output directory is not writable: " + destinationFile.getParentFile());
 return;
 }

 // Open input file
 inputFormatContext = avformat.avformat_alloc_context();
 if (avformat.avformat_open_input(inputFormatContext, sourceFile.getAbsolutePath(), null, null) < 0) {
 System.out.println("Failed to open input file: " + sourceFile.getAbsolutePath());
 return;
 }

 // Find stream information
 if (avformat.avformat_find_stream_info(inputFormatContext, (PointerPointer) null) < 0) {
 System.out.println("Failed to retrieve input stream information.");
 return;
 }

 // Find video stream
 int videoStreamIndex = avformat.av_find_best_stream(inputFormatContext, avutil.AVMEDIA_TYPE_VIDEO, -1, -1, (AVCodec) null, 0);
 if (videoStreamIndex < 0) {
 System.out.println("Failed to find video stream in input file.");
 return;
 }

 // Initialize input codec context
 inputCodecContext = avcodec.avcodec_alloc_context3(null);
 avcodec.avcodec_parameters_to_context(inputCodecContext, inputFormatContext.streams(videoStreamIndex).codecpar());

 AVCodec decoder = avcodec.avcodec_find_decoder(inputCodecContext.codec_id());
 if (decoder == null || avcodec.avcodec_open2(inputCodecContext, decoder, (PointerPointer) null) < 0) {
 System.out.println("Failed to open video decoder.");
 return;
 }

 // Allocate output format context
 if (avformat.avformat_alloc_output_context2(outputFormatContext, null, "mpegts", destinationFile.getAbsolutePath()) < 0) {
 System.out.println("Failed to allocate output format context.");
 return;
 }

 // Initialize output codec
 AVCodec encoder = avcodec.avcodec_find_encoder_by_name("mpeg2video");
 if (encoder == null) {
 System.out.println("Failed to find MPEG2 video encoder.");
 return;
 }

 outputCodecContext = avcodec.avcodec_alloc_context3(encoder);
 if (outputCodecContext == null) {
 System.out.println("Failed to allocate output codec context.");
 return;
 }
 
 if ((outputFormatContext.oformat().flags() & avformat.AVFMT_GLOBALHEADER) != 0) {
 outputCodecContext.flags(outputCodecContext.flags() | avcodec.AV_CODEC_FLAG_GLOBAL_HEADER);
 }


 //outputCodecContext.codec_id(avcodec.AV_CODEC_ID_MPEG2VIDEO);
 outputCodecContext.codec_id(encoder.id());
 outputCodecContext.codec_type(avutil.AVMEDIA_TYPE_VIDEO);
 outputCodecContext.width(1920);
 outputCodecContext.height(1080);
 outputCodecContext.pix_fmt(avutil.AV_PIX_FMT_YUV420P);
 outputCodecContext.time_base(avutil.av_make_q(1, 25));
 outputCodecContext.bit_rate(4000000);
 outputCodecContext.gop_size(12);

 if ((outputFormatContext.oformat().flags() & avformat.AVFMT_GLOBALHEADER) != 0) {
 outputCodecContext.flags(outputCodecContext.flags() | avcodec.AV_CODEC_FLAG_GLOBAL_HEADER);
 }

 
 
 if (avcodec.avcodec_open2(outputCodecContext, encoder, (PointerPointer) null) < 0) {
 System.out.println("Failed to open video encoder.");
 return;
 }

 // Create output stream
 AVStream videoStream = avformat.avformat_new_stream(outputFormatContext, encoder);
 if (videoStream == null) {
 System.out.println("Failed to create video stream.");
 return;
 }

 avcodec.avcodec_parameters_from_context(videoStream.codecpar(), outputCodecContext);
 
 System.out.println("Destination file path before trying to open the file is: " + destinationFile);

 if ((outputFormatContext.oformat().flags() & avformat.AVFMT_NOFILE) == 0) {
 // Ensure the output path has the correct extension
 String outputPath = destinationFile.getAbsolutePath().replace("\\", "/") + ".avchd";
 System.out.println("Normalized output path: " + outputPath);

 // Try opening the output file
 int ret = avformat.avio_open(outputFormatContext.pb(), outputPath, avformat.AVIO_FLAG_WRITE);
 if (ret < 0) {
 BytePointer errorBuffer = new BytePointer(avutil.AV_ERROR_MAX_STRING_SIZE);
 avutil.av_strerror(ret, errorBuffer, errorBuffer.capacity());
 System.out.println("Failed to open output file: " + errorBuffer.getString());
 return;
 }
 }


 // Write header
 if (avformat.avformat_write_header(outputFormatContext, (PointerPointer) null) < 0) {
 System.out.println("Failed to write header to output file.");
 return;
 }


 // Packet processing loop
 AVPacket packet = new AVPacket();
 while (avformat.av_read_frame(inputFormatContext, packet) >= 0) {
 if (packet.stream_index() == videoStreamIndex) {
 if (avcodec.avcodec_send_packet(inputCodecContext, packet) >= 0) {
 AVFrame frame = avutil.av_frame_alloc();
 while (avcodec.avcodec_receive_frame(inputCodecContext, frame) >= 0) {
 if (avcodec.avcodec_send_frame(outputCodecContext, frame) >= 0) {
 AVPacket encodedPacket = new AVPacket();
 while (avcodec.avcodec_receive_packet(outputCodecContext, encodedPacket) >= 0) {
 encodedPacket.stream_index(videoStream.index());
 avformat.av_interleaved_write_frame(outputFormatContext, encodedPacket);
 avcodec.av_packet_unref(encodedPacket);
 }
 }
 avutil.av_frame_unref(frame);
 }
 avutil.av_frame_free(frame);
 }
 }
 avcodec.av_packet_unref(packet);
 }

 // Write trailer
 avformat.av_write_trailer(outputFormatContext);
 System.out.println("Conversion completed successfully.");
 
 if (avcodec.avcodec_send_frame(outputCodecContext, null) >= 0) {
 AVPacket encodedPacket = new AVPacket();
 while (avcodec.avcodec_receive_packet(outputCodecContext, encodedPacket) >= 0) {
 encodedPacket.stream_index(videoStream.index());
 avformat.av_interleaved_write_frame(outputFormatContext, encodedPacket);
 avcodec.av_packet_unref(encodedPacket);
 }
 }

 } catch (Exception e) {
 e.printStackTrace();
 } finally {
 // Cleanup
 avcodec.avcodec_free_context(inputCodecContext);
 avcodec.avcodec_free_context(outputCodecContext);
 avformat.avformat_close_input(inputFormatContext);

 if (outputFormatContext != null && outputFormatContext.pb() != null) {
 avformat.avio_closep(outputFormatContext.pb());
 }
 avformat.avformat_free_context(outputFormatContext);
 }
 }
 
 private boolean validateFileCreation(File destinationFile) {
 // Check if the parent directory exists and is writable
 File parentDir = destinationFile.getParentFile();
 if (parentDir == null || !parentDir.exists()) {
 System.out.println("Parent directory does not exist: " + parentDir);
 return false;
 }
 if (!parentDir.canWrite()) {
 System.out.println("Cannot write to parent directory: " + parentDir);
 return false;
 }

 // Check if the file exists and is writable
 if (destinationFile.exists()) {
 if (!destinationFile.canWrite()) {
 System.out.println("Destination file is not writable: " + destinationFile);
 return false;
 }
 } else {
 // If the file doesn't exist, try to create it to verify writability
 try {
 if (!destinationFile.createNewFile()) {
 System.out.println("Unable to create destination file: " + destinationFile);
 return false;
 }
 // Delete the file after successful creation to avoid residual files
 destinationFile.delete();
 } catch (IOException e) {
 System.out.println("File creation failed: " + e.getMessage());
 return false;
 }
 }

 return true;
 }
 
}





A few caveats :


- 

-
I did explore FFmpeg and GStreamer for this project. GStreamer was inconclusive, with available version for it that were too old for use with my current state of STS4.27 and Java 17, even if this version of Java is under long-term support...


-
I've used AI to tell me about the options and suggest ways to build this thing, since multimedia handling is very far away from my skillset. I don't have a good conceptual grasp of video formats and how they transfrom from one to another.








The issue, as I have identified it, occurs at these lines :


// Ensure the destination file is writable
 if (!destinationFile.canWrite()) {
 JOptionPane.showMessageDialog(null, "Output file is not writable.", "File Error", JOptionPane.ERROR_MESSAGE);
 return;
 }



^^ And this, while temporarily commented out for testing, it meant to compensate for an issue that occurs here in the conversion function :


if ((outputFormatContext.oformat().flags() & avformat.AVFMT_NOFILE) == 0) {
 // Ensure the output path has the correct extension
 String outputPath = destinationFile.getAbsolutePath().replace("\\", "/") + ".avchd";
 System.out.println("Normalized output path: " + outputPath);

 // Try opening the output file
 int ret = avformat.avio_open(outputFormatContext.pb(), outputPath, avformat.AVIO_FLAG_WRITE);
 if (ret < 0) {
 BytePointer errorBuffer = new BytePointer(avutil.AV_ERROR_MAX_STRING_SIZE);
 avutil.av_strerror(ret, errorBuffer, errorBuffer.capacity());
 System.out.println("Failed to open output file: " + errorBuffer.getString());
 return;
 }
 }



The idea here is that the avio_open() function requires the use of the a valid file path that it can open to be able to write it.


Padadoxically, the file conversion seems to work, but the project crashes with a fatal error in the console :


Selected file: E:\TestConveresions\sample_960x540.mov
Save location: E:\TestConveresions
Converting MOV to AVCHD...
Destination file path before trying to open the file is: E:\TestConveresions\sample_960x540_20241231
Normalized output path: E:/TestConveresions/sample_960x540_20241231.avchd
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffcffb0868b, pid=11020, tid=14436
#
# JRE version: OpenJDK Runtime Environment Temurin-21.0.5+11 (21.0.5+11) (build 21.0.5+11-LTS)
# Java VM: OpenJDK 64-Bit Server VM Temurin-21.0.5+11 (21.0.5+11-LTS, mixed mode, emulated-client, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64)
# Problematic frame:
# C 0x00007ffcffb0868b
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# E:\STS4 Workspace\MMConverter\hs_err_pid11020.log
[80.882s][warning][os] Loading hsdis library failed
#
# If you would like to submit a bug report, please visit:
# https://github.com/adoptium/adoptium-support/issues
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
[AVFormatContext @ 000002528adcea40] Opening 'E:\TestConveresions\sample_960x540.mov' for reading
[file @ 000002528ae51c40] Setting default whitelist 'file,crypto,data'
[mov,mp4,m4a,3gp,3g2,mj2 @ 000002528adcea40] Format mov,mp4,m4a,3gp,3g2,mj2 probed with size=2048 and score=100
[mov,mp4,m4a,3gp,3g2,mj2 @ 000002528adcea40] ISO: File Type Major Brand: qt 
[mov,mp4,m4a,3gp,3g2,mj2 @ 000002528adcea40] Unknown dref type 0x206c7275 size 12
[mov,mp4,m4a,3gp,3g2,mj2 @ 000002528adcea40] Processing st: 0, edit list 0 - media time: 2002, duration: 400410
[mov,mp4,m4a,3gp,3g2,mj2 @ 000002528adcea40] Offset DTS by 2002 to make first pts zero.
[mov,mp4,m4a,3gp,3g2,mj2 @ 000002528adcea40] Setting codecpar->delay to 2 for stream st: 0
[mov,mp4,m4a,3gp,3g2,mj2 @ 000002528adcea40] Before avformat_find_stream_info() pos: 1320742 bytes read:38225 seeks:1 nb_streams:1
[h264 @ 000002528ae62780] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 000002528ae62780] Decoding VUI
[h264 @ 000002528ae62780] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 000002528ae62780] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 000002528ae62780] Decoding VUI
[h264 @ 000002528ae62780] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 000002528ae62780] nal_unit_type: 6(SEI), nal_ref_idc: 0
[h264 @ 000002528ae62780] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 000002528ae62780] Format yuv420p chosen by get_format().
[h264 @ 000002528ae62780] Reinit context to 960x544, pix_fmt: yuv420p
[h264 @ 000002528ae62780] no picture 
[mov,mp4,m4a,3gp,3g2,mj2 @ 000002528adcea40] All info found
[mov,mp4,m4a,3gp,3g2,mj2 @ 000002528adcea40] After avformat_find_stream_info() pos: 51943 bytes read:90132 seeks:2 frames:1
[h264 @ 000002528ae62780] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 000002528ae62780] Decoding VUI
[h264 @ 000002528ae62780] nal_unit_type: 8(PPS), nal_ref_idc: 3
[mpeg2video @ 000002528ae8e700] intra_quant_bias = 96 inter_quant_bias = 0




If I refer to the error log, I get this. It is partial, as I'm not sure SO will take all of it (quite long), but still might have enough to be relevant :


Host: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz, 8 cores, 31G, Windows 11 , 64 bit Build 26100 (10.0.26100.2454)


--------------- T H R E A D ---------------

Current thread (0x00000252d030b340): JavaThread "AWT-EventQueue-0" [_thread_in_native, id=14436, stack(0x000000a4e2b00000,0x000000a4e2c00000) (1024K)]

Stack: [0x000000a4e2b00000,0x000000a4e2c00000], sp=0x000000a4e2bfdf30, free space=1015k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C 0x00007ffcffb0868b

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j org.bytedeco.ffmpeg.global.avformat.avio_open(Lorg/bytedeco/ffmpeg/avformat/AVIOContext;Ljava/lang/String;I)I+0
j home.multimeida.mmconverter.MMConverterInterface.convertMovToAvchd(Ljava/io/File;Ljava/io/File;)V+1120
j home.multimeida.mmconverter.MMConverterInterface.lambda$2(Ljavax/swing/JRadioButton;Ljavax/swing/JRadioButton;Ljava/awt/event/ActionEvent;)V+347
j home.multimeida.mmconverter.MMConverterInterface$$Lambda+0x000002528c0c7778.actionPerformed(Ljava/awt/event/ActionEvent;)V+13
j javax.swing.AbstractButton.fireActionPerformed(Ljava/awt/event/ActionEvent;)V+84 java.desktop@21.0.5
j javax.swing.AbstractButton$Handler.actionPerformed(Ljava/awt/event/ActionEvent;)V+5 java.desktop@21.0.5
j javax.swing.DefaultButtonModel.fireActionPerformed(Ljava/awt/event/ActionEvent;)V+34 java.desktop@21.0.5
j javax.swing.DefaultButtonModel.setPressed(Z)V+117 java.desktop@21.0.5
j javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Ljava/awt/event/MouseEvent;)V+35 java.desktop@21.0.5
j java.awt.Component.processMouseEvent(Ljava/awt/event/MouseEvent;)V+64 java.desktop@21.0.5
j javax.swing.JComponent.processMouseEvent(Ljava/awt/event/MouseEvent;)V+23 java.desktop@21.0.5
J 2581 c1 java.awt.Component.processEvent(Ljava/awt/AWTEvent;)V java.desktop@21.0.5 (220 bytes) @ 0x00000252fa62719c [0x00000252fa627020+0x000000000000017c]
J 2580 c1 java.awt.Container.processEvent(Ljava/awt/AWTEvent;)V java.desktop@21.0.5 (22 bytes) @ 0x00000252fa627d9c [0x00000252fa627cc0+0x00000000000000dc]
J 2406 c1 java.awt.Component.dispatchEventImpl(Ljava/awt/AWTEvent;)V java.desktop@21.0.5 (785 bytes) @ 0x00000252fa670f14 [0x00000252fa670040+0x0000000000000ed4]
J 2325 c1 java.awt.Container.dispatchEventImpl(Ljava/awt/AWTEvent;)V java.desktop@21.0.5 (129 bytes) @ 0x00000252fa64e93c [0x00000252fa64e8a0+0x000000000000009c]
J 2608 c1 java.awt.LightweightDispatcher.retargetMouseEvent(Ljava/awt/Component;ILjava/awt/event/MouseEvent;)V java.desktop@21.0.5 (372 bytes) @ 0x00000252fa61c364 [0x00000252fa61b9e0+0x0000000000000984]
J 2578 c1 java.awt.LightweightDispatcher.processMouseEvent(Ljava/awt/event/MouseEvent;)Z java.desktop@21.0.5 (268 bytes) @ 0x00000252fa628a54 [0x00000252fa6284c0+0x0000000000000594]
J 2474 c1 java.awt.LightweightDispatcher.dispatchEvent(Ljava/awt/AWTEvent;)Z java.desktop@21.0.5 (73 bytes) @ 0x00000252fa699bbc [0x00000252fa699a60+0x000000000000015c]
J 2325 c1 java.awt.Container.dispatchEventImpl(Ljava/awt/AWTEvent;)V java.desktop@21.0.5 (129 bytes) @ 0x00000252fa64e914 [0x00000252fa64e8a0+0x0000000000000074]
J 2473 c1 java.awt.Window.dispatchEventImpl(Ljava/awt/AWTEvent;)V java.desktop@21.0.5 (23 bytes) @ 0x00000252fa699654 [0x00000252fa6994e0+0x0000000000000174]
J 1838 c1 java.awt.EventQueue.dispatchEventImpl(Ljava/awt/AWTEvent;Ljava/lang/Object;)V java.desktop@21.0.5 (139 bytes) @ 0x00000252fa3bec64 [0x00000252fa3beb20+0x0000000000000144]
J 1837 c1 java.awt.EventQueue$4.run()Ljava/lang/Void; java.desktop@21.0.5 (60 bytes) @ 0x00000252fa3c0504 [0x00000252fa3c0460+0x00000000000000a4]
J 1836 c1 java.awt.EventQueue$4.run()Ljava/lang/Object; java.desktop@21.0.5 (5 bytes) @ 0x00000252fa3c0a04 [0x00000252fa3c09c0+0x0000000000000044]
J 1778 c1 java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;Ljava/security/AccessControlContext;)Ljava/lang/Object; java.base@21.0.5 (22 bytes) @ 0x00000252fa4601d4 [0x00000252fa45ffa0+0x0000000000000234]
J 1832 c1 java.awt.EventQueue.dispatchEvent(Ljava/awt/AWTEvent;)V java.desktop@21.0.5 (80 bytes) @ 0x00000252fa44f14c [0x00000252fa44eae0+0x000000000000066c]
J 1846 c1 java.awt.EventDispatchThread.pumpOneEventForFilters(I)V java.desktop@21.0.5 (106 bytes) @ 0x00000252fa3ba544 [0x00000252fa3ba2e0+0x0000000000000264]
j java.awt.EventDispatchThread.pumpEventsForFilter(ILjava/awt/Conditional;Ljava/awt/EventFilter;)V+35 java.desktop@21.0.5
j java.awt.EventDispatchThread.pumpEventsForHierarchy(ILjava/awt/Conditional;Ljava/awt/Component;)V+11 java.desktop@21.0.5
j java.awt.EventDispatchThread.pumpEvents(ILjava/awt/Conditional;)V+4 java.desktop@21.0.5
j java.awt.EventDispatchThread.pumpEvents(Ljava/awt/Conditional;)V+3 java.desktop@21.0.5
j java.awt.EventDispatchThread.run()V+9 java.desktop@21.0.5
v ~StubRoutines::call_stub 0x00000252fa08100d

siginfo: EXCEPTION_ACCESS_VIOLATION (0xc0000005), writing address 0x0000000000000000




If anyone has a perspective on this, it'd be appreciated.


The catch 22 in this project is that pre-creating the file is not a good idea, since avio_open has a purpose in-built method for that (I tried). Error checking everything about Java's File class in terms of setting pathways and creating and deleting files is not problematic. Likewise, permissions are all fine (Full Control in source and target folders) ; I've tested default C drive folders, which have restritions, to a separate volume and removable media, to no effect. Likewise, FFmpeg requires a forward slash, "/" in file paths, whereas Java does the backslash, generally. That's been handled with the replace method in the above conditioning, also to no effect.


The basic contradiction in the project seems to be that the error tries open a file that does not exist, with a valid source and destination file, and if I try to create a placeholder file wiht an acvhd extension at the event handling for the Convert button, it still errors out ; meanwhile, FFmpeg allegedly handles the file creation at its core, but requires a valid path to be passed ; I've tried with and without a filename, with and without an extension. I'm not able to resovle it.


The excessive error handling conditions are in an effort to isolate the problem, which I think I've done.


There also seems to be a compatibility between mpegts and acvhd, which is why I also had that format specified in the conversion function, without result.


I also have the idea to be able to do this without having to install any libraries locally or having to set path variables, which is an aspect that both GStreamer and FFmpeg have.


Nearest suggestion I've found is this : integrate ffmpeg with spring boot


AI remains hopeless for resolving this issue.


-
-
FFMPEG in Node.js : Conversion Failed
11 juillet 2024, par cuneyttylerI have a small node.js web app. I use like this in a get request :


app.get('/api/voice/:gender/:voice/:pitch', function(req, res){
 if(req.params.pitch == "1" || req.params.pitch == "1.0") {
 const file = "./voices/" + req.params.gender.toLowerCase() + "/" + req.params.voice + ".mp3"
 res.download(file);
 return
 }

 const inputFile = "./voices/" + req.params.gender.toLowerCase() + "/" + req.params.voice + ".mp3"
 const output_file = "./Audio/Temp/" + req.params.voice + ".mp3"
 ffmpeg()
 .input(inputFile)
 .audioCodec('pcm_s16le') // Set the audio codec to PCM with 16-bit depth
 .audioFrequency(44100) // Set the sample rate
 .on('error', function(err) {
 console.error('Error while converting:', err);
 })
 .on('end', function() {
 // res.download(output_file)
 })
 .save(output_file);

 });



It gives
Conversion Failed
error :

[2024-07-11T18:11:22.880Z] Error while converting: Error: ffmpeg exited with code 1: Conversion failed!

 at ChildProcess.<anonymous> (d:\Dev\Anima\Client\node_modules\fluent-ffmpeg\lib\processor.js:180:22)
 at ChildProcess.emit (d:\Dev\Anima\Client\lib\events.js:519:28)
 at ChildProcess._handle.onexit (d:\Dev\Anima\Client\lib\internal\child_process.js:294:12)
 at Process.callbackTrampoline (node:internal/async_hooks:130:17) {stack: 'Error: ffmpeg exited with code 1: Conversion …Trampoline (node:internal/async_hooks:130:17)', message: 'ffmpeg exited with code 1: Conversion failed!
'}
</anonymous>


When I use same code in a node.js desktop(.exe) app, it successfully runs. When I use it in an express.js app, it fails. Error message is not clear. What is the issue ?


-
webrtc to rtmp send video from camera to rtmp link
14 avril 2024, par Leo-Mahendrai cant send the video from webrtc which is converted to bufferd data for every 10seconds and send to server.js where it takes it via websockets and convert it to flv format using ffmpeg.


i am trying to send it to rtmp server named restreamer for start, here i tried to convert the buffer data and send it to rtmp link using ffmpeg commands, where i initially started to suceesfully save the file from webrtc to mp4 format for a duration of 2-3 minute.


after i tried to use webrtc to send video data for every 10 seconds and in server i tried to send it to rtmp but i cant send it, but i can see the connection of rtmp url and server is been taken place but i cant see the video i can see the logs in rtmp server as


2024-04-14 12:35:45 ts=2024-04-14T07:05:45Z level=INFO component="RTMP" msg="no streams available" action="INVALID" address=":1935" client="172.17.0.1:37700" path="/3d30c5a9-2059-4843-8957-da963c7bc19b.stream" who="PUBLISH"
2024-04-14 12:35:45 ts=2024-04-14T07:05:45Z level=INFO component="RTMP" msg="no streams available" action="INVALID" address=":1935" client="172.17.0.1:37716" path="/3d30c5a9-2059-4843-8957-da963c7bc19b.stream" who="PUBLISH"
2024-04-14 12:35:45 ts=2024-04-14T07:05:45Z level=INFO component="RTMP" msg="no streams available" action="INVALID" address=":1935" client="172.17.0.1:37728" path="/3d30c5a9-2059-4843-8957-da963c7bc19b.stream" who="PUBLISH" 



my frontend code


const handleSendVideo = async () => {
 console.log("start");
 
 if (!ws) {
 console.error('WebSocket connection not established.');
 return;
 }
 
 try {
 const videoStream = await navigator.mediaDevices.getUserMedia({ video: true });
 const mediaRecorder = new MediaRecorder(videoStream);
 
 const requiredFrameSize = 460800;
 const frameDuration = 10 * 1000; // 10 seconds in milliseconds
 
 mediaRecorder.ondataavailable = async (event) => {
 if (ws.readyState !== WebSocket.OPEN) {
 console.error('WebSocket connection is not open.');
 return;
 }
 
 if (event.data.size > 0) {
 const arrayBuffer = await event.data.arrayBuffer();
 const uint8Array = new Uint8Array(arrayBuffer);
 
 const width = videoStream.getVideoTracks()[0].getSettings().width;
 const height = videoStream.getVideoTracks()[0].getSettings().height;
 
 const numFrames = Math.ceil(uint8Array.length / requiredFrameSize);
 
 for (let i = 0; i < numFrames; i++) {
 const start = i * requiredFrameSize;
 const end = Math.min((i + 1) * requiredFrameSize, uint8Array.length);
 let frameData = uint8Array.subarray(start, end);
 
 // Pad or trim the frameData to match the required size
 if (frameData.length < requiredFrameSize) {
 // Pad with zeros to reach the required size
 const paddedData = new Uint8Array(requiredFrameSize);
 paddedData.set(frameData, 0);
 frameData = paddedData;
 } else if (frameData.length > requiredFrameSize) {
 // Trim to match the required size
 frameData = frameData.subarray(0, requiredFrameSize);
 }
 
 const dataToSend = {
 buffer: Array.from(frameData), // Convert Uint8Array to array of numbers
 width: width,
 height: height,
 pixelFormat: 'yuv420p',
 mode: 'SendRtmp'
 };
 
 console.log("Sending frame:", i);
 ws.send(JSON.stringify(dataToSend));
 }
 }
 };
 
 // Start recording and send data every 10 seconds
 mediaRecorder.start(frameDuration);
 
 console.log("MediaRecorder started.");
 } catch (error) {
 console.error('Error accessing media devices or starting recorder:', error);
 }
 };



and my backend


wss.on('connection', (ws) => {
 console.log('WebSocket connection established.');

 ws.on('message', async (data) => {
 try {
 const parsedData = JSON.parse(data);

 if (parsedData.mode === 'SendRtmp' && Array.isArray(parsedData.buffer)) {
 const { buffer, pixelFormat, width, height } = parsedData;
 const bufferArray = Buffer.from(buffer);

 await sendRtmpVideo(bufferArray, pixelFormat, width, height);
 } else {
 console.log('Received unknown or invalid mode or buffer data');
 }
 } catch (error) {
 console.error('Error parsing WebSocket message:', error);
 }
 });

 ws.on('close', () => {
 console.log('WebSocket connection closed.');
 });
 });
 const sendRtmpVideo = async (frameBuffer, pixelFormat, width, height) => {
 console.log("ffmpeg data",frameBuffer)
 try {
 const ratio = `${width}x${height}`;
 const ffmpegCommand = [
 '-re',
 '-f', 'rawvideo',
 '-pix_fmt', pixelFormat,
 '-s', ratio,
 '-i', 'pipe:0',
 '-c:v', 'libx264',
 '-preset', 'fast', // Specify the preset for libx264
 '-b:v', '3000k', // Specify the video bitrate
 '-loglevel', 'debug',
 '-f', 'flv',
 // '-flvflags', 'no_duration_filesize', 
 RTMPLINK
 ];


 const ffmpeg = spawn('ffmpeg', ffmpegCommand);

 ffmpeg.on('exit', (code, signal) => {
 if (code === 0) {
 console.log('FFmpeg process exited successfully.');
 } else {
 console.error(`FFmpeg process exited with code ${code} and signal ${signal}`);
 }
 });

 ffmpeg.on('error', (error) => {
 console.error('FFmpeg spawn error:', error);
 });

 ffmpeg.stderr.on('data', (data) => {
 console.error(`FFmpeg stderr: ${data}`);
 });

 ffmpeg.stdin.write(frameBuffer, (err) => {
 if (err) {
 console.error('Error writing to FFmpeg stdin:', err);
 } else {
 console.log('Data written to FFmpeg stdin successfully.');
 }
 ffmpeg.stdin.end(); // Close stdin after writing the buffer
 });
 } catch (error) {
 console.error('Error in sendRtmpVideo:', error);
 }
 };