
Recherche avancée
Médias (91)
-
Les Miserables
9 décembre 2019, par
Mis à jour : Décembre 2019
Langue : français
Type : Textuel
-
VideoHandle
8 novembre 2019, par
Mis à jour : Novembre 2019
Langue : français
Type : Video
-
Somos millones 1
21 juillet 2014, par
Mis à jour : Juin 2015
Langue : français
Type : Video
-
Un test - mauritanie
3 avril 2014, par
Mis à jour : Avril 2014
Langue : français
Type : Textuel
-
Pourquoi Obama lit il mes mails ?
4 février 2014, par
Mis à jour : Février 2014
Langue : français
-
IMG 0222
6 octobre 2013, par
Mis à jour : Octobre 2013
Langue : français
Type : Image
Autres articles (88)
-
Websites made with MediaSPIP
2 mai 2011, parThis page lists some websites based on MediaSPIP.
-
Creating farms of unique websites
13 avril 2011, parMediaSPIP platforms can be installed as a farm, with a single "core" hosted on a dedicated server and used by multiple websites.
This allows (among other things) : implementation costs to be shared between several different projects / individuals rapid deployment of multiple unique sites creation of groups of like-minded sites, making it possible to browse media in a more controlled and selective environment than the major "open" (...) -
Organiser par catégorie
17 mai 2013, parDans MédiaSPIP, une rubrique a 2 noms : catégorie et rubrique.
Les différents documents stockés dans MédiaSPIP peuvent être rangés dans différentes catégories. On peut créer une catégorie en cliquant sur "publier une catégorie" dans le menu publier en haut à droite ( après authentification ). Une catégorie peut être rangée dans une autre catégorie aussi ce qui fait qu’on peut construire une arborescence de catégories.
Lors de la publication prochaine d’un document, la nouvelle catégorie créée sera proposée (...)
Sur d’autres sites (6406)
-
FFmpeg Overwiting Playlist
30 septembre 2024, par Program-Me-RevI'm working on an implementation where I aim to generate a DASH Playlist from Raw Camera2 data in Android Java using FFmpeg


However , the current implementation only produces Three .m4s files regardless of how long the recording lasts . My goal is to create a playlist with 1-second .m4s Segments , but the output only includes the following files , and the video length doesn't exceed 2 seconds :


- playlist.mpd
- init.m4s
- 1.m4s
- 2.m4s



While the temporary files are created as expected , the .m4s files stop after these two segments . Additionally , only the last 2 seconds of the recording are retained , no matter how long the recording runs


The FFmpeg output indicates that FFmpeg is repeatedly overwriting the previously generated playlist , which may explain why the recording doesn't extend beyond 2 seconds


FFmpeg version : 6.0


package rev.ca.rev_media_dash_camera2;

 import android.app.Activity;
 import android.content.Context;
 import android.media.Image;
 import android.util.Log;
 import android.util.Size;

 import androidx.annotation.NonNull;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.ImageAnalysis;
 import androidx.camera.core.ImageProxy;
 import androidx.camera.core.Preview;
 import androidx.camera.lifecycle.ProcessCameraProvider;
 import androidx.camera.view.PreviewView;
 import androidx.core.content.ContextCompat;
 import androidx.lifecycle.LifecycleOwner;

 import com.arthenica.ffmpegkit.FFmpegKit;
 import com.arthenica.ffmpegkit.ReturnCode;
 import com.google.common.util.concurrent.ListenableFuture;

 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;

 public class RevCameraCapture {
 private static final String REV_TAG = "RevCameraCapture";

 private final Context revContext;
 private final ExecutorService revExecutorService;
 private final String revOutDirPath = "/storage/emulated/0/Documents/Owki/rev_web_rtc_live_chat_temp_files/_abc_rev_uploads_temp";
 private boolean isRevRecording;
 private File revTempFile;
 private int revFrameCount = 0; // Counter for frames captured

 public RevCameraCapture(Context revContext) {
 this.revContext = revContext;

 revInitDir(revOutDirPath);
 revCheckOrCreatePlaylist();

 revExecutorService = Executors.newSingleThreadExecutor();
 }

 private void revInitDir(String revDirPath) {
 // Create a File object for the directory
 File revNestedDir = new File(revDirPath);

 // Check if the directory exists, if not, create it
 if (!revNestedDir.exists()) {
 boolean revResult = revNestedDir.mkdirs(); // mkdirs() creates the whole path
 if (revResult) {
 Log.e(REV_TAG, ">>> Directories created successfully.");
 } else {
 Log.e(REV_TAG, ">>> Failed to create directories.");
 }
 } else {
 Log.e(REV_TAG, ">>> Directories already exist.");
 }
 }

 private void revCheckOrCreatePlaylist() {
 File revPlaylistFile = new File(revOutDirPath, "rev_playlist.mpd");
 if (!revPlaylistFile.exists()) {
 // Create an empty playlist if it doesn't exist
 try {
 FileOutputStream revFos = new FileOutputStream(revPlaylistFile);
 revFos.write("".getBytes());
 revFos.close();
 } catch (IOException e) {
 Log.e(REV_TAG, ">>> Error creating initial rev_playlist : ", e);
 }
 }
 }


 private void revStartFFmpegProcess() {
 // Ensure revTempFile exists before processing
 if (revTempFile == null || !revTempFile.exists()) {
 Log.e(REV_TAG, ">>> Temporary file does not exist for FFmpeg processing.");
 return;
 }

 // FFmpeg command to convert the temp file to DASH format and append to the existing rev_playlist
 String ffmpegCommand = "-f rawvideo -pixel_format yuv420p -video_size 704x704 " + "-i " + revTempFile.getAbsolutePath() + " -c:v mpeg4 -b:v 1M " + "-f dash -seg_duration 1 -use_template 1 -use_timeline 1 " + "-init_seg_name 'init.m4s' -media_seg_name '$Number$.m4s' " + revOutDirPath + "/rev_playlist.mpd -loglevel debug";


 FFmpegKit.executeAsync(ffmpegCommand, session -> {
 ReturnCode returnCode = session.getReturnCode();
 if (ReturnCode.isSuccess(returnCode)) {
 // Optionally handle success, e.g., log or notify that the process completed successfully
 } else {
 Log.e(REV_TAG, ">>> FFmpeg process failed with return code : " + returnCode);
 }
 });
 }


 public void revStartCamera() {
 isRevRecording = true;

 ListenableFuture<processcameraprovider> revCameraProviderFuture = ProcessCameraProvider.getInstance(revContext);

 revCameraProviderFuture.addListener(() -> {
 try {
 ProcessCameraProvider revCameraProvider = revCameraProviderFuture.get();
 revBindPreview(revCameraProvider);
 revBindImageAnalysis(revCameraProvider);
 } catch (ExecutionException | InterruptedException e) {
 Log.e(REV_TAG, ">>> Failed to start camera : ", e);
 }
 }, ContextCompat.getMainExecutor(revContext));
 }

 private void revBindPreview(ProcessCameraProvider revCameraProvider) {
 CameraSelector revCameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();

 PreviewView previewView = ((Activity) revContext).findViewById(R.id.previewView);
 Preview preview = new Preview.Builder().build();
 preview.setSurfaceProvider(previewView.getSurfaceProvider());

 revCameraProvider.unbindAll();
 revCameraProvider.bindToLifecycle((LifecycleOwner) revContext, revCameraSelector, preview);
 }

 private void revBindImageAnalysis(@NonNull ProcessCameraProvider revCameraProvider) {
 ImageAnalysis revImageAnalysis = new ImageAnalysis.Builder().setTargetResolution(new Size(640, 480)) // Lower the resolution to reduce memory consumption
 .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST).build();

 revImageAnalysis.setAnalyzer(ContextCompat.getMainExecutor(revContext), this::revAnalyze);
 CameraSelector revCameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();

 revCameraProvider.bindToLifecycle((LifecycleOwner) revContext, revCameraSelector, revImageAnalysis);
 }

 @androidx.annotation.OptIn(markerClass = androidx.camera.core.ExperimentalGetImage.class)
 private void revAnalyze(@NonNull ImageProxy revImageProxy) {
 try {
 revProcessImageFrame(revImageProxy);
 } catch (Exception e) {
 Log.e(REV_TAG, ">>> Error processing revImage frame", e);
 } finally {
 revImageProxy.close(); // Always close the revImageProxy
 }
 }

 @androidx.annotation.OptIn(markerClass = androidx.camera.core.ExperimentalGetImage.class)
 private void revProcessImageFrame(@NonNull ImageProxy revImageProxy) {
 Image revImage = revImageProxy.getImage();
 if (revImage != null) {
 byte[] revImageBytes = revConvertYUV420888ToByteArray(revImage);
 revWriteFrameToTempFile(revImageBytes); // Write frame to a temporary file
 }
 revImageProxy.close(); // Close the ImageProxy to release the revImage buffer
 }

 private byte[] revConvertYUV420888ToByteArray(Image revImage) {
 Image.Plane[] planes = revImage.getPlanes();
 ByteBuffer revBufferY = planes[0].getBuffer();
 ByteBuffer revBufferU = planes[1].getBuffer();
 ByteBuffer revBufferV = planes[2].getBuffer();

 int revWidth = revImage.getWidth();
 int revHeight = revImage.getHeight();

 int revSizeY = revWidth * revHeight;
 int revSizeUV = (revWidth / 2) * (revHeight / 2); // U and V sizes are half the Y size

 // Total size = Y + U + V
 byte[] revData = new byte[revSizeY + 2 * revSizeUV];

 // Copy Y plane
 revBufferY.get(revData, 0, revSizeY);

 // Copy U and V planes, accounting for row stride and pixel stride
 int revOffset = revSizeY;
 int revPixelStrideU = planes[1].getPixelStride();
 int rowStrideU = planes[1].getRowStride();
 int revPixelStrideV = planes[2].getPixelStride();
 int rowStrideV = planes[2].getRowStride();

 // Copy U plane
 for (int row = 0; row < revHeight / 2; row++) {
 for (int col = 0; col < revWidth / 2; col++) {
 revData[revOffset++] = revBufferU.get(row * rowStrideU + col * revPixelStrideU);
 }
 }

 // Copy V plane
 for (int row = 0; row < revHeight / 2; row++) {
 for (int col = 0; col < revWidth / 2; col++) {
 revData[revOffset++] = revBufferV.get(row * rowStrideV + col * revPixelStrideV);
 }
 }

 return revData;
 }


 private void revWriteFrameToTempFile(byte[] revImageBytes) {
 revExecutorService.execute(() -> {
 try {
 // Create a new temp file for each segment if needed
 if (revTempFile == null || revFrameCount == 0) {
 revTempFile = File.createTempFile("vid_segment_", ".yuv", new File(revOutDirPath));
 }

 try (FileOutputStream revFos = new FileOutputStream(revTempFile, true)) {
 revFos.write(revImageBytes);
 }

 revFrameCount++;

 // Process after 60 frames (2 second for 30 fps)
 if (revFrameCount >= 60 && isRevRecording) {
 revStartFFmpegProcess(); // Process the segment with FFmpeg
 revFrameCount = 0; // Reset the frame count
 revTempFile = null; // Reset temp file for the next segment
 }

 } catch (IOException e) {
 Log.e(REV_TAG, ">>> Error writing frame to temp file : ", e);
 }
 });
 }

 public void revStopCamera() {
 isRevRecording = false;
 if (revTempFile != null && revTempFile.exists()) {
 revTempFile.delete(); // Clean up the temporary file
 revTempFile = null; // Reset the temp file reference
 }
 }
 }


 package rev.ca.rev_media_dash_camera2;

 import android.os.Bundle;

 import androidx.appcompat.app.AppCompatActivity;

 public class MainActivity extends AppCompatActivity {
 private RevCameraCapture revCameraCapture;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 revCameraCapture = new RevCameraCapture(this);
 }

 @Override
 protected void onStart() {
 super.onStart();
 try {
 revCameraCapture.revStartCamera();
 } catch (Exception e) {
 e.printStackTrace();
 }
 }

 @Override
 protected void onStop() {
 super.onStop();
 revCameraCapture.revStopCamera(); // Ensure camera is stopped when not in use
 }
 }
</processcameraprovider>


-
High quality screen capture using ffmpeg on wayland [closed]
27 novembre 2024, par Charlie Benger-StevensonRunning hyprland/wayland on arch.


I want a reasonable quality (for say youtube) screen capture.


ffmpeg -device /dev/dri/card1 -re -f kmsgrab -i - -vf 'hwmap=derive_device=vaapi,hwdownload,format=bgr0' -s 1920x1080 -c:v mpeg2video -b:v 1M -t 5 ~/Recordings/screencap.avi



This should set a bitrate of 1M but the output is super blocky with a much lower bitrate than specified by the b:v flag.


What am I doing wrong ?


-
WordPress Analytics plugin WP-Piwik reaches version 1.0.0 (and 50,000 active users)
29 mai 2015, par André Bräkling — PluginsAfter six years of development, we are proud to announce the 1.0.0 release of our WP-Piwik WordPress plugin !
Started as a simple plugin to show a selection of statistics within the WordPress dashboard, WP-Piwik has become a full Piwik integration plugin. The plugin automatically adds the Piwik tracking code to your WordPress sites. The plugin displays your analytics reports directly within the WordPress admin panel. WordPress networks (“multisite”), CDN URLs and the Piwik proxy script are also supported.
According to WordPress.org the plugin is being used by more than 50,000 WordPress sites !
This article explains how to install WP-Piwik and how to configure it to work with your Piwik instance.
Install WP-Piwik
You can get WP-Piwik using WordPress’ plugin management. Login to your WordPress admin dashboard and go to « Plugins » → « Add New ». Enter « WP-Piwik » into the search field at the top right, press enter and next to WP-Piwik choose « Install Now ».
If you want to use WP-Piwik in your simple WordPress blog you can just click « Activate Plugin » and WP-Piwik will ask you to configure your Piwik connection.
Running a WordPress network/multisite you can choose to « Network Activate » the plugin after the installation process. In this case, WP-Piwik will be a fully automated feature of your WordPress network automatically tracking your sites in the same Piwik instance in separate Websites.
Alternatively you can download WP-Piwik manually from the WordPress website and upload all files to your `wp-content/plugins` directory.
Configure your Piwik connection
WP-Piwik lets you choose between three connection modes :
- Self-hosted (HTTP API) : This is the default option for a self-hosted Piwik and should work for most configurations. You just have to know your Piwik URL, which is the URL you enter to access Piwik, and your auth token (see below). WP-Piwik will connect to Piwik using http(s)-requests.
- Self-hosted (PHP API) : Choose this, if your self-hosted Piwik and WordPress are running on the same machine and you know the full server path to your Piwik instance. Beside the full server path, you also need to know your auth token (see below).
- Cloud-hosted (Piwik Pro) : If you are using a cloud-hosted Piwik by Piwik Pro, you just need to know your user name and your auth token (see below).
Setting up WP-Piwik
To configure WP-Piwik you will need to specify your Authentication token.
- If the site you want to track in Piwik is already configured in your Piwik, you only need to specify a token_auth for a user with `view` permission.
- If you want WP-Piwik to create the website in Piwik (or if you use WP-Piwik in network mode which requires to be able to configure your sites), you should specify a token_auth which has Super User access (after the setting up phase is completed you can set the authentication token back to the token of a `view` user).
To find your token_auth in Piwik, click on your user name in the right right corner of your Piwik dashboard, then click the « API » in the left menu. The API page displays your auth token in a colored box, just behind the “&token_auth=” string. The screenshot below shows the token_auth anonymous, but your real one will be an alpha numerous random string like a1ec31524a8eabc7a546d71d68b28d17.
That’s it. After you entered your connection data and submitted the form, WP-Piwik will welcome you with some information :
You can now start to configure WP-Piwik and enable the tracking code. Learn about any setting by clicking on the small question mark sign. If you have any problem configuring or using WP-Piwik feel free to use the WordPress support forum related to WP-Piwik.
Translating WP-Piwik
We invite you to join our translation community at Transifex and help to translate WP-Piwik in more languages !
Happy WordPress Analytics !