Recherche avancée

Médias (2)

Mot : - Tags -/documentation

Autres articles (90)

  • Amélioration de la version de base

    13 septembre 2013

    Jolie sélection multiple
    Le plugin Chosen permet d’améliorer l’ergonomie des champs de sélection multiple. Voir les deux images suivantes pour comparer.
    Il suffit pour cela d’activer le plugin Chosen (Configuration générale du site > Gestion des plugins), puis de configurer le plugin (Les squelettes > Chosen) en activant l’utilisation de Chosen dans le site public et en spécifiant les éléments de formulaires à améliorer, par exemple select[multiple] pour les listes à sélection multiple (...)

  • Multilang : améliorer l’interface pour les blocs multilingues

    18 février 2011, par

    Multilang est un plugin supplémentaire qui n’est pas activé par défaut lors de l’initialisation de MediaSPIP.
    Après son activation, une préconfiguration est mise en place automatiquement par MediaSPIP init permettant à la nouvelle fonctionnalité d’être automatiquement opérationnelle. Il n’est donc pas obligatoire de passer par une étape de configuration pour cela.

  • ANNEXE : Les plugins utilisés spécifiquement pour la ferme

    5 mars 2010, par

    Le site central/maître de la ferme a besoin d’utiliser plusieurs plugins supplémentaires vis à vis des canaux pour son bon fonctionnement. le plugin Gestion de la mutualisation ; le plugin inscription3 pour gérer les inscriptions et les demandes de création d’instance de mutualisation dès l’inscription des utilisateurs ; le plugin verifier qui fournit une API de vérification des champs (utilisé par inscription3) ; le plugin champs extras v2 nécessité par inscription3 (...)

Sur d’autres sites (9755)

  • Python aiortc : How to record audio and video come from client in the same file ? [closed]

    22 décembre 2024, par Chris P

    I have an aiortc app, which html5 client send data (microphone,camera) into server.

    


    In server side i sucessfully played this two streams seperatly.

    


    But when i try to record using aiortc MediaRecorder helper class, only the voice is recording, and the video is dropped (mp4 format).

    


    I think this is due sync issue.

    


    The audio_frame and the video_frame (each pair of them) have different time_base.
(I don't know if this is strange).
But it also has different time.

    


    I can share code, but couldn't help at all right now.

    


    Edit : I also tried to synchronize them client side with no luck

    


    // Synchronize tracks
async function synchronizeTracks(localStream) {
    const videoTrack = localStream.getVideoTracks()[0];
    const audioTrack = localStream.getAudioTracks()[0];

    const syncedStream = new MediaStream();

    // Add tracks to the synchronized stream
    syncedStream.addTrack(videoTrack);
    syncedStream.addTrack(audioTrack);

    // Video and audio processors
    const videoProcessor = new MediaStreamTrackProcessor({ track: videoTrack });
    const audioProcessor = new MediaStreamTrackProcessor({ track: audioTrack });

    const videoReader = videoProcessor.readable.getReader();
    const audioReader = audioProcessor.readable.getReader();

    const videoWriter = new MediaStreamTrackGenerator({ kind: "video" }).writable.getWriter();
    const audioWriter = new MediaStreamTrackGenerator({ kind: "audio" }).writable.getWriter();

    const syncThreshold = 5; // Maximum allowable time difference in milliseconds
    let baseTimestamp = null;

    async function processTracks() {
        try {
            while (true) {
                const [videoResult, audioResult] = await Promise.all([
                    videoReader.read(),
                    audioReader.read(),
                ]);

                if (videoResult.done || audioResult.done) break;

                const videoFrame = videoResult.value;
                const audioFrame = audioResult.value;

                // Initialize base timestamp if needed
                if (baseTimestamp === null) {
                    baseTimestamp = Math.min(videoFrame.timestamp, audioFrame.timestamp);
                }

                const videoRelativeTimestamp = videoFrame.timestamp - baseTimestamp;
                const audioRelativeTimestamp = audioFrame.timestamp - baseTimestamp;

                const timeDifference = videoRelativeTimestamp - audioRelativeTimestamp;

                if (Math.abs(timeDifference) <= syncThreshold) {
                    // Frames are in sync
                    await videoWriter.write(videoFrame);
                    await audioWriter.write(audioFrame);
                } else if (timeDifference > 0) {
                    // Video is ahead, wait for audio to catch up
                    await audioWriter.write(audioFrame);
                    // Reuse video frame on the next loop
                    videoReader.releaseLock();
                } else {
                    // Audio is ahead, wait for video to catch up
                    await videoWriter.write(videoFrame);
                    // Reuse audio frame on the next loop
                    audioReader.releaseLock();
                }

                // Release frames
                videoFrame.close();
                audioFrame.close();
            }
        } catch (error) {
            console.error("Error in track synchronization:", error);
        } finally {
            videoReader.releaseLock();
            audioReader.releaseLock();
            videoWriter.close();
            audioWriter.close();
        }
    }

    processTracks();

    return syncedStream;
}



    


    python code to improve :

    


    class SyncClientTracksForRecording:
    def __init__(self, audio_track, video_track, audio_track_sync_q, video_track_sync_q):
        self.audio_track = audio_track
        self.video_track = video_track
        self.audio_track_sync_q = audio_track_sync_q
        self.video_track_sync_q = video_track_sync_q

        # Time bases
        self.audio_time_base = fractions.Fraction(1, 48000)  # 48 kHz audio
        self.video_time_base = fractions.Fraction(1, 90000)  # 90 kHz video

        # Elapsed time tracking
        self.audio_elapsed_time = 0.0
        self.video_elapsed_time = 0.0

        # Stop signal for synchronization loop
        self.stop_signal = False

    async def sync(self):
        while not self.stop_signal:
            try:
                # Receive audio and video frames concurrently
                audio_task = asyncio.create_task(self.audio_track.recv())
                video_task = asyncio.create_task(self.video_track.recv())

                audio_frame, video_frame = await asyncio.gather(audio_task, video_task)

                # Set time bases
                audio_frame.time_base = self.audio_time_base
                video_frame.time_base = self.video_time_base

                # Calculate and assign PTS values
                audio_frame.pts = int(self.audio_elapsed_time / float(self.audio_time_base))
                video_frame.pts = int(self.video_elapsed_time / float(self.video_time_base))

                # Increment elapsed time
                self.audio_elapsed_time += 0.020  # Assuming 20 ms audio frame duration
                self.video_elapsed_time += 1 / 30  # Assuming 30 fps video frame rate

                # Enqueue frames
                await asyncio.gather(
                    self.audio_track_sync_q.put(audio_frame),
                    self.video_track_sync_q.put(video_frame),
                )

            except Exception as e:
                print(f"Error in sync loop: {e}")
                break

    def stop(self):
        """Stop the synchronization loop."""
        self.stop_signal = True



    


  • FFPMEG : stream local video to UDP address, make client aware about video length and current frame time offset (make stream seekable ?)

    17 décembre 2014, par klim

    Just started to use FFMPEG. This is a really great library which is capable of video life transcoding and streaming.

    I use following commands to transcode and stream local video file to UDP address :
    ffmpeg -y -re -i inputvideo.mpeg2 -vsync 1 -vcodec mpeg4 -b 1600k -r 15 -crf 20 -acodec aac -ar 44100 -strict -2 -f mpegts udp ://192.168.1.30:1234

    It works smooth. I can open this udp address in VLC player and play life stream.

    Does anybody know how to make client aware about video duration and current time stamp ?

    Ideally would be nice to make stream seekable, as far as I understand it is not possible, but at least I would like to tell VLC client the total duration of the video and current frame time stamp, so it could show the progress.

    Thanks.

  • Is there any problem in my FFMPEG encoder client code ?

    29 janvier 2024, par kyhnz

    I am trying to write code have function of capture video stream, encode as hevc265 and send to server as UDP :

    


    // There can some unnecessary library imports, rule 1: If it is ok, don&#x27;t touch it!&#xA;&#xA;#include <iostream>&#xA;#include <sys></sys>types.h>&#xA;#include &#xA;#include <cstring>&#xA;#include <sys></sys>socket.h>&#xA;#include <arpa></arpa>inet.h>&#xA;#include <netinet></netinet>in.h> &#xA;#include <string>&#xA;#include <cstdlib>&#xA;#include <cstdio>&#xA;&#xA;extern "C"&#xA;{&#xA;#include <libavutil></libavutil>frame.h>&#xA;#include <libavdevice></libavdevice>avdevice.h>&#xA;#include <libavformat></libavformat>avformat.h>&#xA;#include <libavcodec></libavcodec>avcodec.h>&#xA;#include <libavutil></libavutil>imgutils.h>&#xA;#include <libavcodec></libavcodec>packet.h>&#xA;#include <libavcodec></libavcodec>codec_id.h>&#xA;#include <libavutil></libavutil>error.h>&#xA;#include <libavutil></libavutil>error.h>&#xA;#include <libavutil></libavutil>opt.h>&#xA;}&#xA;&#xA;#define PORT 9999&#xA;#define IP_ADDRESS "127.0.0.1"&#xA;&#xA;using namespace std;&#xA;&#xA;int main(){&#xA;    const int width = 1080;&#xA;    const int height = 720;&#xA;    const int fps = 18; &#xA;    const auto resulation = "1080x720";&#xA;    const auto device = "/dev/video0";&#xA;    const auto format = "v4l2";&#xA;    const AVCodecID codec_id = AV_CODEC_ID_H265;&#xA;&#xA;    avdevice_register_all();&#xA;    avformat_network_init();&#xA;    AVFormatContext *formatContext = nullptr;&#xA;&#xA;    AVDictionary *format_opts = nullptr;&#xA;    av_dict_set(&amp;format_opts, "framerate", "18", 0);;&#xA;    av_dict_set(&amp;format_opts, "video_size", resulation, 0);&#xA;    &#xA;    const AVInputFormat *inputFormat = av_find_input_format(format);&#xA;    if (!inputFormat)&#xA;    {&#xA;        cerr &lt;&lt; "Unknown input format: " &lt;&lt; format &lt;&lt; endl;&#xA;        return 1;&#xA;    }&#xA;    cout &lt;&lt; "Input format: "&lt;&lt; format &lt;&lt; endl;&#xA;&#xA;    const AVCodec *codec = avcodec_find_encoder(codec_id);&#xA;    if (!codec) {&#xA;        cerr &lt;&lt; "Codec can&#x27;t find "&lt;&lt; codec_id &lt;&lt; endl;&#xA;        return 1;&#xA;    }&#xA;    cout &lt;&lt; "Found codec: "&lt;&lt; codec_id &lt;&lt; endl;&#xA;&#xA;    AVCodecContext *avctx = avcodec_alloc_context3(codec);&#xA;    if (!avctx) {&#xA;        cerr &lt;&lt; "Error: Could not create encoder!" &lt;&lt; endl;&#xA;        return 1;&#xA;    }&#xA;    cout &lt;&lt; "Create encoder. " &lt;&lt; endl;&#xA;&#xA;&#xA;    avctx->bit_rate = 1000000;&#xA;    avctx->width = width; &#xA;    avctx->height = height; &#xA;    avctx->pix_fmt = AV_PIX_FMT_YUV420P; &#xA;    avctx->time_base = (AVRational){1, fps};&#xA;    avctx->framerate = (AVRational){fps, 1};&#xA;    avctx->gop_size = fps*2;&#xA;    avctx->refs = 3;&#xA;&#xA;    av_opt_set(avctx->priv_data, "preset", "medium", 0);&#xA;    av_opt_set(avctx->priv_data, "crf", "18", 0);&#xA;    av_opt_set(avctx->priv_data, "tune", "zerolatency", 0);&#xA;&#xA;    if (avcodec_open2(avctx, codec, nullptr) &lt; 0) {&#xA;        cerr &lt;&lt; "Error: Couldn&#x27;t open codec" &lt;&lt; endl;&#xA;        return 1;&#xA;    }&#xA;    cout &lt;&lt; "Open codec succesfully." &lt;&lt; endl;&#xA;&#xA;    int open_input = avformat_open_input(&amp;formatContext, device,&#xA;                                            const_cast<avinputformat>(inputFormat), &amp;format_opts);&#xA;    if (open_input != 0)&#xA;    {&#xA;        cerr &lt;&lt; "Device cant open " &lt;&lt; device &lt;&lt; endl;&#xA;        return 1;&#xA;    }&#xA;    cout &lt;&lt; "Device active: " &lt;&lt; device &lt;width = avctx->width;&#xA;    frame->height = avctx->height;&#xA;    frame->format = avctx->pix_fmt;&#xA;&#xA;    if(av_frame_get_buffer(frame, 0) != 0){&#xA;        cerr &lt;&lt; "Error: video frame " &lt;&lt; endl;&#xA;        return 1;&#xA;    }cout &lt;&lt; "Video frame has been created." &lt;&lt; endl;&#xA;&#xA;    if(av_frame_make_writable(frame) != 0){&#xA;        cerr &lt;&lt; "Error: frame is not writable" &lt;&lt; endl;&#xA;        return 1;&#xA;    }&#xA;&#xA;    AVPacket *packet= av_packet_alloc();&#xA;    if (!packet) {&#xA;        cerr &lt;&lt; "error: has not been created packet" &lt;&lt; endl;&#xA;    }&#xA;&#xA;    av_dump_format(formatContext, 0, device, 0);&#xA;    av_dict_free(&amp;format_opts);&#xA;    &#xA;    int socket_client = socket(AF_INET, SOCK_DGRAM, 0);&#xA;    if (socket_client == -1) {&#xA;        cerr &lt;&lt; "Error: socket!" &lt;&lt; endl;&#xA;        exit(EXIT_FAILURE);&#xA;    }&#xA;    cout &lt;&lt; "Socket has been created" &lt;&lt; endl;&#xA;&#xA;    struct sockaddr_in serverAddr = {0};&#xA;    serverAddr.sin_family = AF_INET;&#xA;    serverAddr.sin_port = htons(PORT);&#xA;    serverAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);&#xA;&#xA;    while (true) {&#xA;        if (av_read_frame(formatContext, packet) != 0) {&#xA;            cerr &lt;&lt; "Error" &lt;&lt; endl;&#xA;            av_packet_unref(packet);&#xA;            continue;&#xA;        }&#xA;&#xA;        frame->data[7] = packet->data; &#xA;        frame->linesize[7] = packet->size;&#xA;&#xA;        if (avcodec_send_frame(avctx, frame) != 0){&#xA;            cerr &lt;&lt; "Error: Frame sending is missing ---> "&lt;&lt; &amp;av_strerror &lt;&lt; endl;&#xA;            av_packet_unref(packet);&#xA;            continue;&#xA;        }&#xA;&#xA;        if (avcodec_receive_packet(avctx, packet) != 0){&#xA;            cerr &lt;&lt; "Error: Packet giving is missing! ---> " &lt;&lt; &amp;av_strerror &lt;&lt; endl;&#xA;            av_packet_unref(packet);&#xA;            continue;&#xA;        }&#xA;&#xA;        ssize_t snd = sendto(socket_client, packet->data, packet->size,&#xA;                            MSG_CONFIRM, (struct sockaddr *)&amp;serverAddr,&#xA;                            sizeof(serverAddr));&#xA;&#xA;        if(snd == -1){&#xA;            cerr &lt;&lt; "Error: Data sending failed !" &lt;&lt; endl;&#xA;            av_packet_unref(packet);&#xA;            continue;&#xA;        }else {&#xA;            cout &lt;&lt; "Data sending succesfully" &lt;&lt; endl;&#xA;        }&#xA;&#xA;        av_packet_unref(packet);&#xA;        av_frame_unref(frame);&#xA;    }&#xA;&#xA;    av_frame_free(&amp;frame);&#xA;    av_packet_free(&amp;packet);&#xA;    close(socket_client);&#xA;    avformat_free_context(formatContext);&#xA;    avformat_close_input(&amp;formatContext);&#xA;    avformat_network_deinit();&#xA;&#xA;    return 0;&#xA;}&#xA;</avinputformat></cstdio></cstdlib></string></cstring></iostream>

    &#xA;

    There is such an output, I do not understand the reason yet :

    &#xA;

    [video4linux2,v4l2 @ 0x643732e80b40] The V4L2 driver changed the video from 1080x720 to 1280x720&#xA;[video4linux2,v4l2 @ 0x643732e80b40] The V4L2 driver changed the video from 1280x720 to 640x480&#xA;[video4linux2,v4l2 @ 0x643732e80b40] The driver changed the time per frame from 1/18 to 1/30&#xA;

    &#xA;

    Is there any problem in my encoder client code ?

    &#xA;

    In addition, i can't send datas to server.

    &#xA;