Recherche avancée

Médias (2)

Mot : - Tags -/documentation

Autres articles (36)

  • Supporting all media types

    13 avril 2011, par

    Unlike most software and media-sharing platforms, MediaSPIP aims to manage as many different media types as possible. The following are just a few examples from an ever-expanding list of supported formats : images : png, gif, jpg, bmp and more audio : MP3, Ogg, Wav and more video : AVI, MP4, OGV, mpg, mov, wmv and more text, code and other data : OpenOffice, Microsoft Office (Word, PowerPoint, Excel), web (html, CSS), LaTeX, Google Earth and (...)

  • Contribute to documentation

    13 avril 2011

    Documentation is vital to the development of improved technical capabilities.
    MediaSPIP welcomes documentation by users as well as developers - including : critique of existing features and functions articles contributed by developers, administrators, content producers and editors screenshots to illustrate the above translations of existing documentation into other languages
    To contribute, register to the project users’ mailing (...)

  • Selection of projects using MediaSPIP

    2 mai 2011, par

    The examples below are representative elements of MediaSPIP specific uses for specific projects.
    MediaSPIP farm @ Infini
    The non profit organizationInfini develops hospitality activities, internet access point, training, realizing innovative projects in the field of information and communication technologies and Communication, and hosting of websites. It plays a unique and prominent role in the Brest (France) area, at the national level, among the half-dozen such association. Its members (...)

Sur d’autres sites (4105)

  • Android FFMPEG - Low FPS & File Size is massive

    2 mai 2018, par Alexzander Flores

    I am new to Android app development and I have been asked to make a video splitter app. I am trying to use FFMPEG, but the library size is massive and makes the .APK file 140MB. How can I solve this ? Similar apps are around 15MBs in size.

    Also, the framerate starts at 30FPS and drops to around 2.2FPS over time when trying to split a 30 second long video into two parts. How can I solve this ? This is my code currently :

    package splicer.com.splicer;

    import android.Manifest;
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.database.Cursor;
    import android.media.MediaMetadataRetriever;
    import android.media.MediaScannerConnection;
    import android.net.Uri;
    import android.provider.MediaStore;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.text.method.ScrollingMovementMethod;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;

    import com.github.hiteshsondhi88.libffmpeg.ExecuteBinaryResponseHandler;
    import com.github.hiteshsondhi88.libffmpeg.FFmpeg;
    import com.github.hiteshsondhi88.libffmpeg.LoadBinaryResponseHandler;
    import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegNotSupportedException;

    public class MainActivity extends AppCompatActivity {

       private Button button;
       private TextView textView;
       private FFmpeg ffmpeg;

       static {
           System.loadLibrary("native-lib");
       }

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

           ffmpeg = FFmpeg.getInstance(getApplicationContext());
           try {
               ffmpeg.loadBinary(new LoadBinaryResponseHandler() {

                   @Override
                   public void onStart() {}

                   @Override
                   public void onFailure() {}

                   @Override
                   public void onSuccess() {}

                   @Override
                   public void onFinish() {}
               });
           } catch(FFmpegNotSupportedException e) {
               e.printStackTrace();
           }

           textView = (TextView) findViewById(R.id.textView);
           textView.setY(200);
           textView.setHeight(700);
           textView.setMovementMethod(new ScrollingMovementMethod());

           button = (Button) findViewById(R.id.button);
           button.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View view) {
                   openGallery();
               }
           });
       }

       /**
        * A native method that is implemented by the 'native-lib' native library,
        * which is packaged with this application.
        */
       public native String stringFromJNI();

       public void openGallery() {
           if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
               ActivityCompat.requestPermissions(this, new String [] {Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
           }

           if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
               ActivityCompat.requestPermissions(this, new String [] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
           }

           Intent gallery = new Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
           startActivityForResult(gallery, 100);
       }

       public String getRealPathFromURI(Context context, Uri contentUri) {
           Cursor cursor = null;
           try {
               String[] proj = { MediaStore.Images.Media.DATA };
               cursor = context.getContentResolver().query(contentUri,  proj, null, null, null);
               int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
               cursor.moveToFirst();
               return cursor.getString(column_index);
           } finally {
               if (cursor != null) {
                   cursor.close();
               }
           }
       }

       @Override
       protected void onActivityResult(int requestCode, int resultCode, final Intent intent) {
           super.onActivityResult(requestCode, resultCode, intent);
           if(resultCode == RESULT_OK && requestCode == 100) {
               MediaMetadataRetriever retriever = new MediaMetadataRetriever();
               try {
                   retriever.setDataSource(getBaseContext(), intent.getData());
                   String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
                   long splitCount = Long.valueOf(time) / 1000 / 15;
                   if(splitCount > 1) {
                       final String path = getRealPathFromURI(getBaseContext(), Uri.parse(intent.getData().toString()));

                       for(int a = 0, start = 0; a < splitCount; ++a, start += 15) {
                           // I am only testing with .mp4s atm, this will change before production
                           final String targetPath = path.replace(".mp4", "_" + (a + 1) + ".mp4");

                           ffmpeg.execute(new String [] {
                                   "-r",
                                   "1",
                                   "-i",
                                   path,
                                   "-ss",
                                   String.valueOf(start),
                                   "-t",
                                   String.valueOf(start + 15),
                                   "-r",
                                   "24",
                                   targetPath
                           }, new ExecuteBinaryResponseHandler() {
                               @Override
                               public void onStart() {}

                               @Override
                               public void onProgress(String message) {
                                   textView.setText("onProcess: " + message);
                               }

                               @Override
                               public void onFailure(String message) {
                                   textView.setText("onFailure: " + message + " --- " + path);
                               }

                               @Override
                               public void onSuccess(String message) {
                                   textView.setText("onSuccess:" + message);
                                   MediaScannerConnection.scanFile(getBaseContext(),
                                   new String [] { targetPath }, null,
                                   new MediaScannerConnection.OnScanCompletedListener() {
                                       public void onScanCompleted(String path, Uri uri) {}
                                   });
                               }

                               @Override
                               public void onFinish() {}
                           });
                       }
                   }
               } catch(Exception e) {
                   e.printStackTrace();
               } finally {
                   retriever.release();
               }
           }
       }
    }

    I don’t believe everything here is as optimal as it could be, but I’m just trying to prove the concept at the moment. Any help in the right direction would be amazing, thank you !

  • How to restream IPTV playlist with Nginx RTMP, FFmpeg, and Python without recording, but getting HTTP 403 error ? [closed]

    1er avril, par boyuna1720

    I have an IPTV playlist from a provider that allows only one user to connect and watch. I want to restream this playlist through my own server without recording it and in a lightweight manner. I’m using Nginx RTMP, FFmpeg, and Python TCP for the setup, but I keep getting an HTTP 403 error when trying to access the stream.

    


    Here’s a summary of my setup :

    


    Nginx RTMP : Used for streaming.

    


    FFmpeg : Used to handle the video stream.

    


    Python TCP : Trying to handle the connection between my server and the IPTV source.

    


    #!/usr/bin/env python3&#xA;&#xA;import sys&#xA;import socket&#xA;import threading&#xA;import requests&#xA;import time&#xA;&#xA;def accept_connections(server_socket, clients, clients_lock):&#xA;    """&#xA;    Continuously accept new client connections, perform a minimal read of the&#xA;    client&#x27;s HTTP request, send back a valid HTTP/1.1 response header, and&#xA;    add the socket to the broadcast list.&#xA;    """&#xA;    while True:&#xA;        client_socket, addr = server_socket.accept()&#xA;        print(f"[&#x2B;] New client connected from {addr}")&#xA;        threading.Thread(&#xA;            target=handle_client,&#xA;            args=(client_socket, addr, clients, clients_lock),&#xA;            daemon=True&#xA;        ).start()&#xA;&#xA;def handle_client(client_socket, addr, clients, clients_lock):&#xA;    """&#xA;    Read the client&#x27;s HTTP request minimally, send back a proper HTTP/1.1 200 OK header,&#xA;    and then add the socket to our broadcast list.&#xA;    """&#xA;    try:&#xA;        # Read until we reach the end of the request headers&#xA;        request_data = b""&#xA;        while b"\r\n\r\n" not in request_data:&#xA;            chunk = client_socket.recv(1024)&#xA;            if not chunk:&#xA;                break&#xA;            request_data &#x2B;= chunk&#xA;&#xA;        # Send a proper HTTP response header to satisfy clients like curl&#xA;        response_header = (&#xA;            "HTTP/1.1 200 OK\r\n"&#xA;            "Content-Type: application/octet-stream\r\n"&#xA;            "Connection: close\r\n"&#xA;            "\r\n"&#xA;        )&#xA;        client_socket.sendall(response_header.encode("utf-8"))&#xA;&#xA;        with clients_lock:&#xA;            clients.append(client_socket)&#xA;        print(f"[&#x2B;] Client from {addr} is ready to receive stream.")&#xA;    except Exception as e:&#xA;        print(f"[!] Error handling client {addr}: {e}")&#xA;        client_socket.close()&#xA;&#xA;def read_from_source_and_broadcast(source_url, clients, clients_lock):&#xA;    """&#xA;    Continuously connect to the source URL (following redirects) using custom headers&#xA;    so that it mimics a curl-like request. In case of connection errors (e.g. connection reset),&#xA;    wait a bit and then try again.&#xA;    &#xA;    For each successful connection, stream data in chunks and broadcast each chunk&#xA;    to all connected clients.&#xA;    """&#xA;    # Set custom headers to mimic curl&#xA;    headers = {&#xA;        "User-Agent": "curl/8.5.0",&#xA;        "Accept": "*/*"&#xA;    }&#xA;&#xA;    while True:&#xA;        try:&#xA;            print(f"[&#x2B;] Fetching from source URL (with redirects): {source_url}")&#xA;            with requests.get(source_url, stream=True, allow_redirects=True, headers=headers) as resp:&#xA;                if resp.status_code >= 400:&#xA;                    print(f"[!] Got HTTP {resp.status_code} from the source. Retrying in 5 seconds.")&#xA;                    time.sleep(5)&#xA;                    continue&#xA;&#xA;                # Stream data and broadcast each chunk&#xA;                for chunk in resp.iter_content(chunk_size=4096):&#xA;                    if not chunk:&#xA;                        continue&#xA;                    with clients_lock:&#xA;                        for c in clients[:]:&#xA;                            try:&#xA;                                c.sendall(chunk)&#xA;                            except Exception as e:&#xA;                                print(f"[!] A client disconnected or send failed: {e}")&#xA;                                c.close()&#xA;                                clients.remove(c)&#xA;        except requests.exceptions.RequestException as e:&#xA;            print(f"[!] Source connection error, retrying in 5 seconds: {e}")&#xA;            time.sleep(5)&#xA;&#xA;def main():&#xA;    if len(sys.argv) != 3:&#xA;        print(f"Usage: {sys.argv[0]}  <port>")&#xA;        sys.exit(1)&#xA;&#xA;    source_url = sys.argv[1]&#xA;    port = int(sys.argv[2])&#xA;&#xA;    # Create a TCP socket to listen for incoming connections&#xA;    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)&#xA;    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)&#xA;    server_socket.bind(("0.0.0.0", port))&#xA;    server_socket.listen(5)&#xA;    print(f"[&#x2B;] Listening on port {port}...")&#xA;&#xA;    # List of currently connected client sockets&#xA;    clients = []&#xA;    clients_lock = threading.Lock()&#xA;&#xA;    # Start a thread to accept incoming client connections&#xA;    t_accept = threading.Thread(&#xA;        target=accept_connections,&#xA;        args=(server_socket, clients, clients_lock),&#xA;        daemon=True&#xA;    )&#xA;    t_accept.start()&#xA;&#xA;    # Continuously read from the source URL and broadcast to connected clients&#xA;    read_from_source_and_broadcast(source_url, clients, clients_lock)&#xA;&#xA;if __name__ == "__main__":&#xA;    main()&#xA;</port>

    &#xA;

    When i write command python3 proxy_server.py &#x27;http://channelurl&#x27; 9999&#xA;I getting error.

    &#xA;

    [&#x2B;] Listening on port 9999...&#xA;[&#x2B;] Fetching from source URL (with redirects): http://ate91060.cdn-akm.me:80/dc31a19e5a6a/fc5e38e28e/325973&#xA;[!] Got HTTP 403 from the source. Retrying in 5 seconds.&#xA;^CTraceback (most recent call last):&#xA;  File "/home/namepirate58/nginx-1.23.1/proxy_server.py", line 127, in <module>&#xA;    main()&#xA;  File "/home/namepirate58/nginx-1.23.1/proxy_server.py", line 124, in main&#xA;    read_from_source_and_broadcast(source_url, clients, clients_lock)&#xA;  File "/home/namepirate58/nginx-1.23.1/proxy_server.py", line 77, in read_from_source_and_broadcast&#xA;    time.sleep(5)&#xA;KeyboardInterrupt&#xA;</module>

    &#xA;

  • Evolution #4753 (Nouveau) : Styles du privé : listes d’objets (suite des boîtes et des formulaires)

    30 avril 2021

    Les boîtes et les formulaires ont été visuellement « raccordés » ensembles.
    Je pense que logiquement les listes d’objets devraient suivre.
    En fait ce sont 3 variations d’un même composant : une boîte avec entête, corps et pied.

    Pour les listes on peut séparer la question en 2 aspects :

    1) L’emballage extérieur

    Là il s’agirait de reprendre les choix graphiques propres à « l’emballage extérieur » des boîtes et formulaires : bordure, arrondi, espacements.
    Exemple sur l’image suivant où les 3 sont visibles (nb : ceux en colonne sont automatiquement « ressérés », d’où la différence de padding etc.)

    Après en fonction de l’un ou de l’autre, il y aura peut-être lieu d’ajuster le padding ou la taille du titre. Mais pour l’instant ce sont ceux en place.

    2) L’intérieur

    Ensuite je propose de procéder à quelques ajustements à l’intérieur de ces listes.
    Je pense que certains choix ont été faits pour s’accommoder du manque de place en largeur à l’époque, et ne sont plus nécessaires maintenant.

    Pour me faire un idée de ce qui fonctionnerait le mieux, et comprendre les détails visuels qui me gênaient un peu, j’ai parcouru quelques articles de recommandations sur l’ergonomie des data tables.
    Alors ils traitent plutot des fonctionnalités de ces tables dans leur ensemble, mais il y a aussi quelques guidelines visuelles intéressantes.

    Je retiens quelques règles simples :

    • Des espacements suffisants et consistants (le padding quoi)
    • Une taille de police identique partout (au moins dans le tbody). C’est fatiguant pour l’oeil et moins lisible quand on passe sans arrêt d’un taille de police à l’autre sur une même ligne. Et je ne suis pas sûr qu’il y ait forcément besoin de gras pour certains éléments comme les titres ou autres.
    • À quelques exceptions près (id, picto), pas de largeur fixes sur les colonnes, laisser faire le navigateur.

    Donc voilà, c’est pas grand chose à ajuster non plus.
    Les colonnes des tables ont des classes .importante et .secondaire.
    À mon avis elle ne devraient plus avoir d’incidence en vue « normale », mais juste décider quelles colonnes afficher et masquer en vue réduite, dans les colonnes ou ailleurs.

    Donc dans les grandes lignes ça donnerait quelques chose comme ça (juste une maquette) :

    3) Détails

    Enfin pour ces 3 composants, je propose qu’il y ait une classe modificatrice commune pour produire un affichage compact, c’est à dire ressérer tout le contenu.
    Cette classe serait automatiquement appliquée dans les colonnes.

    Ça pourrait être « compact », mais sur d’autres composants pour varier les tailles je suis parti sur mini / large. Donc mini aussi ?