Recherche avancée

Médias (3)

Mot : - Tags -/spip

Autres articles (62)

  • Les formats acceptés

    28 janvier 2010, par

    Les commandes suivantes permettent d’avoir des informations sur les formats et codecs gérés par l’installation local de ffmpeg :
    ffmpeg -codecs ffmpeg -formats
    Les format videos acceptés en entrée
    Cette liste est non exhaustive, elle met en exergue les principaux formats utilisés : h264 : H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 m4v : raw MPEG-4 video format flv : Flash Video (FLV) / Sorenson Spark / Sorenson H.263 Theora wmv :
    Les formats vidéos de sortie possibles
    Dans un premier temps on (...)

  • Ajouter notes et légendes aux images

    7 février 2011, par

    Pour pouvoir ajouter notes et légendes aux images, la première étape est d’installer le plugin "Légendes".
    Une fois le plugin activé, vous pouvez le configurer dans l’espace de configuration afin de modifier les droits de création / modification et de suppression des notes. Par défaut seuls les administrateurs du site peuvent ajouter des notes aux images.
    Modification lors de l’ajout d’un média
    Lors de l’ajout d’un média de type "image" un nouveau bouton apparait au dessus de la prévisualisation (...)

  • Demande de création d’un canal

    12 mars 2010, par

    En fonction de la configuration de la plateforme, l’utilisateur peu avoir à sa disposition deux méthodes différentes de demande de création de canal. La première est au moment de son inscription, la seconde, après son inscription en remplissant un formulaire de demande.
    Les deux manières demandent les mêmes choses fonctionnent à peu près de la même manière, le futur utilisateur doit remplir une série de champ de formulaire permettant tout d’abord aux administrateurs d’avoir des informations quant à (...)

Sur d’autres sites (9435)

  • Play video using mse (media source extension) in google chrome

    23 août 2019, par liyuqihxc

    I’m working on a project that convert rtsp stream (ffmpeg) and play it on the web page (signalr + mse).

    So far it works pretty much as I expected on the latest version of edge and firefox, but not chrome.

    here’s the code

    public class WebmMediaStreamContext
    {
       private Process _ffProcess;
       private readonly string _cmd;
       private byte[] _initSegment;
       private Task _readMediaStreamTask;
       private CancellationTokenSource _cancellationTokenSource;

       private const string _CmdTemplate = "-i {0} -c:v libvpx -tile-columns 4 -frame-parallel 1 -keyint_min 90 -g 90 -f webm -dash 1 pipe:";

       public static readonly byte[] ClusterStart = { 0x1F, 0x43, 0xB6, 0x75, 0x01, 0x00, 0x00, 0x00 };

       public event EventHandler<clusterreadyeventargs> ClusterReadyEvent;

       public WebmMediaStreamContext(string rtspFeed)
       {
           _cmd = string.Format(_CmdTemplate, rtspFeed);
       }

       public async Task StartConverting()
       {
           if (_ffProcess != null)
               throw new InvalidOperationException();

           _ffProcess = new Process();
           _ffProcess.StartInfo = new ProcessStartInfo
           {
               FileName = "ffmpeg/ffmpeg.exe",
               Arguments = _cmd,
               UseShellExecute = false,
               CreateNoWindow = true,
               RedirectStandardOutput = true
           };
           _ffProcess.Start();

           _initSegment = await ParseInitSegmentAndStartReadMediaStream();
       }

       public byte[] GetInitSegment()
       {
           return _initSegment;
       }

       // Find the first cluster, and everything before it is the InitSegment
       private async Task ParseInitSegmentAndStartReadMediaStream()
       {
           Memory<byte> buffer = new byte[10 * 1024];
           int length = 0;
           while (length != buffer.Length)
           {
               length += await _ffProcess.StandardOutput.BaseStream.ReadAsync(buffer.Slice(length));
               int cluster = buffer.Span.IndexOf(ClusterStart);
               if (cluster >= 0)
               {
                   _cancellationTokenSource = new CancellationTokenSource();
                   _readMediaStreamTask = new Task(() => ReadMediaStreamProc(buffer.Slice(cluster, length - cluster).ToArray(), _cancellationTokenSource.Token), _cancellationTokenSource.Token, TaskCreationOptions.LongRunning);
                   _readMediaStreamTask.Start();
                   return buffer.Slice(0, cluster).ToArray();
               }
           }

           throw new InvalidOperationException();
       }

       private void ReadMoreBytes(Span<byte> buffer)
       {
           int size = buffer.Length;
           while (size > 0)
           {
               int len = _ffProcess.StandardOutput.BaseStream.Read(buffer.Slice(buffer.Length - size));
               size -= len;
           }
       }

       // Parse every single cluster and fire ClusterReadyEvent
       private void ReadMediaStreamProc(byte[] bytesRead, CancellationToken cancel)
       {
           Span<byte> buffer = new byte[5 * 1024 * 1024];
           bytesRead.CopyTo(buffer);
           int bufferEmptyIndex = bytesRead.Length;

           do
           {
               if (bufferEmptyIndex &lt; ClusterStart.Length + 4)
               {
                   ReadMoreBytes(buffer.Slice(bufferEmptyIndex, 1024));
                   bufferEmptyIndex += 1024;
               }

               int clusterDataSize = BitConverter.ToInt32(
                   buffer.Slice(ClusterStart.Length, 4)
                   .ToArray()
                   .Reverse()
                   .ToArray()
               );
               int clusterSize = ClusterStart.Length + 4 + clusterDataSize;
               if (clusterSize > buffer.Length)
               {
                   byte[] newBuffer = new byte[clusterSize];
                   buffer.Slice(0, bufferEmptyIndex).CopyTo(newBuffer);
                   buffer = newBuffer;
               }

               if (bufferEmptyIndex &lt; clusterSize)
               {
                   ReadMoreBytes(buffer.Slice(bufferEmptyIndex, clusterSize - bufferEmptyIndex));
                   bufferEmptyIndex = clusterSize;
               }

               ClusterReadyEvent?.Invoke(this, new ClusterReadyEventArgs(buffer.Slice(0, bufferEmptyIndex).ToArray()));

               bufferEmptyIndex = 0;
           } while (!cancel.IsCancellationRequested);
       }
    }
    </byte></byte></byte></clusterreadyeventargs>

    I use ffmpeg to convert the rtsp stream to vp8 WEBM byte stream and parse it to "Init Segment" (ebml head、info、tracks...) and "Media Segment" (cluster), then send it to browser via signalR

    $(function () {

       var mediaSource = new MediaSource();
       var mimeCodec = 'video/webm; codecs="vp8"';

       var video = document.getElementById('video');

       mediaSource.addEventListener('sourceopen', callback, false);
       function callback(e) {
           var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
           var queue = [];

           sourceBuffer.addEventListener('updateend', function () {
               if (queue.length === 0) {
                   return;
               }

               var base64 = queue[0];
               if (base64.length === 0) {
                   mediaSource.endOfStream();
                   queue.shift();
                   return;
               } else {
                   var buffer = new Uint8Array(atob(base64).split("").map(function (c) {
                       return c.charCodeAt(0);
                   }));
                   sourceBuffer.appendBuffer(buffer);
                   queue.shift();
               }
           }, false);

           var connection = new signalR.HubConnectionBuilder()
               .withUrl("/signalr-video")
               .configureLogging(signalR.LogLevel.Information)
               .build();
           connection.start().then(function () {
               connection.stream("InitVideoReceive")
                   .subscribe({
                       next: function(item) {
                           if (queue.length === 0 &amp;&amp; !!!sourceBuffer.updating) {
                               var buffer = new Uint8Array(atob(item).split("").map(function (c) {
                                   return c.charCodeAt(0);
                               }));
                               sourceBuffer.appendBuffer(buffer);
                               console.log(blockindex++ + " : " + buffer.byteLength);
                           } else {
                               queue.push(item);
                           }
                       },
                       complete: function () {
                           queue.push('');
                       },
                       error: function (err) {
                           console.error(err);
                       }
                   });
           });
       }
       video.src = window.URL.createObjectURL(mediaSource);
    })

    chrome just play the video for 3 5 seconds and then stop for buffering, even though there are plenty of cluster transfered and inserted into SourceBuffer.

    here’s the information in chrome ://media-internals/

    Player Properties :

    render_id: 217
    player_id: 1
    origin_url: http://localhost:52531/
    frame_url: http://localhost:52531/
    frame_title: Home Page
    url: blob:http://localhost:52531/dcb25d89-9830-40a5-ba88-33c13b5c03eb
    info: Selected FFmpegVideoDecoder for video decoding, config: codec: vp8 format: 1 profile: vp8 coded size: [1280,720] visible rect: [0,0,1280,720] natural size: [1280,720] has extra data? false encryption scheme: Unencrypted rotation: 0°
    pipeline_state: kSuspended
    found_video_stream: true
    video_codec_name: vp8
    video_dds: false
    video_decoder: FFmpegVideoDecoder
    duration: unknown
    height: 720
    width: 1280
    video_buffering_state: BUFFERING_HAVE_NOTHING
    for_suspended_start: false
    pipeline_buffering_state: BUFFERING_HAVE_NOTHING
    event: PAUSE

    Log

    Timestamp       Property            Value
    00:00:00 00     origin_url          http://localhost:52531/
    00:00:00 00     frame_url           http://localhost:52531/
    00:00:00 00     frame_title         Home Page
    00:00:00 00     url                 blob:http://localhost:52531/dcb25d89-9830-40a5-ba88-33c13b5c03eb
    00:00:00 00     info                ChunkDemuxer: buffering by DTS
    00:00:00 35     pipeline_state      kStarting
    00:00:15 213    found_video_stream  true
    00:00:15 213    video_codec_name    vp8
    00:00:15 216    video_dds           false
    00:00:15 216    video_decoder       FFmpegVideoDecoder
    00:00:15 216    info                Selected FFmpegVideoDecoder for video decoding, config: codec: vp8 format: 1 profile: vp8 coded size: [1280,720] visible rect: [0,0,1280,720] natural size: [1280,720] has extra data? false encryption scheme: Unencrypted rotation: 0°
    00:00:15 216    pipeline_state      kPlaying
    00:00:15 213    duration            unknown
    00:00:16 661    height              720
    00:00:16 661    width               1280
    00:00:16 665    video_buffering_state       BUFFERING_HAVE_ENOUGH
    00:00:16 665    for_suspended_start         false
    00:00:16 665    pipeline_buffering_state    BUFFERING_HAVE_ENOUGH
    00:00:16 667    pipeline_state      kSuspending
    00:00:16 670    pipeline_state      kSuspended
    00:00:52 759    info                Effective playback rate changed from 0 to 1
    00:00:52 759    event               PLAY
    00:00:52 759    pipeline_state      kResuming
    00:00:52 760    video_dds           false
    00:00:52 760    video_decoder       FFmpegVideoDecoder
    00:00:52 760    info                Selected FFmpegVideoDecoder for video decoding, config: codec: vp8 format: 1 profile: vp8 coded size: [1280,720] visible rect: [0,0,1280,720] natural size: [1280,720] has extra data? false encryption scheme: Unencrypted rotation: 0°
    00:00:52 760    pipeline_state      kPlaying
    00:00:52 793    height              720
    00:00:52 793    width               1280
    00:00:52 798    video_buffering_state       BUFFERING_HAVE_ENOUGH
    00:00:52 798    for_suspended_start         false
    00:00:52 798    pipeline_buffering_state    BUFFERING_HAVE_ENOUGH
    00:00:56 278    video_buffering_state       BUFFERING_HAVE_NOTHING
    00:00:56 295    for_suspended_start         false
    00:00:56 295    pipeline_buffering_state    BUFFERING_HAVE_NOTHING
    00:01:20 717    event               PAUSE
    00:01:33 538    event               PLAY
    00:01:35 94     event               PAUSE
    00:01:55 561    pipeline_state      kSuspending
    00:01:55 563    pipeline_state      kSuspended

    Can someone tell me what’s wrong with my code, or dose chrome require some magic configuration to work ?

    Thanks 

    Please excuse my english :)

  • mpc current song bash script fail safe

    21 novembre 2018, par Orophix

    I’ve got a script that loops :

    #!/bin/sh
    while [ true ]
    do
     mpc current > current_song.txt
     mpc idle player
    done

    However sometimes it fails to get the song details and creates a blank file.
    FFMpeg is reading this file and it crashes if its blank. Is there any way to fail safe the script so if the file is blank it adds a certain text ?

    Would the best way be to create a script that tries to read the file and if it turns out blank to insert some text and then sleep for a period of time or is there a more elegant way to do it ?

  • avformat_write_header() return -22 ? [duplicate]

    9 janvier 2019, par TTGroup

    This question already has an answer here :

    I’m using the following code for Re-Stream the exist RTSP stream.

    But it is failed at avformat_write_header(), return value is -22.

    I have searched many times but there is not any solution.

    int ReStream()
       {
           AVOutputFormat *ofmt = NULL;
           //Input AVFormatContext and Output AVFormatContext
           AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
           AVPacket pkt;
           const char *in_filename, *out_filename;
           int ret, i;
           int videoindex = -1;
           int frame_index = 0;
           int64_t start_time = 0;
           //in_filename  = "cuc_ieschool.mov";
           //in_filename  = "cuc_ieschool.mkv";
           //in_filename  = "cuc_ieschool.ts";
           //in_filename  = "cuc_ieschool.mp4";
           //in_filename  = "cuc_ieschool.h264";
           in_filename = "rtsp://admin:Admin@123@192.168.1.81:554/Streaming/Channels/101?transportmode=unicast&amp;profile=Profile_1";//输入URL(Input file URL)
                                            //in_filename  = "shanghai03_p.h264";

           out_filename = "rtsp://localhost/publishlive/livestream";//输出 URL(Output URL)[RTMP]
                                                                    //out_filename = "rtp://233.233.233.233:6666";//输出 URL(Output URL)[UDP]

           av_register_all();
           //Network
           avformat_network_init();
           //Input
           if ((ret = avformat_open_input(&amp;ifmt_ctx, in_filename, 0, 0)) &lt; 0)
           {
               printf("Could not open input file.");
               goto end;
           }
           if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) &lt; 0)
           {
               printf("Failed to retrieve input stream information");
               goto end;
           }

           for (i = 0; i &lt; ifmt_ctx->nb_streams; i++)
           {
               if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
               {
                   videoindex = i;
                   break;
               }
           }

           av_dump_format(ifmt_ctx, 0, in_filename, 0);

           //Output
           ret = avformat_alloc_output_context2(&amp;ofmt_ctx, NULL, "rtsp", out_filename); //RTMP
                                                                                 //avformat_alloc_output_context2(&amp;ofmt_ctx, NULL, "mpegts", out_filename);//UDP
           if (ret &lt; 0)
           {
               char strErr[STR_LENGTH_256];
               av_strerror(AVERROR(ret), strErr, STR_LENGTH_256);
               CommonGlobalUlti::UltiFunctions::WriteRuntimeLogs("avformat_alloc_output_context2() " + gcnew String(strErr));
               goto end;
           }
           if (!ofmt_ctx)
           {
               printf("Could not create output context\n");
               ret = AVERROR_UNKNOWN;
               goto end;
           }
           ofmt = ofmt_ctx->oformat;
           for (i = 0; i &lt; ifmt_ctx->nb_streams; i++)
           {
               //Create output AVStream according to input AVStream
               AVStream *in_stream = ifmt_ctx->streams[i];
               AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
               if (!out_stream)
               {
                   printf("Failed allocating output stream\n");
                   ret = AVERROR_UNKNOWN;
                   goto end;
               }
               //Copy the settings of AVCodecContext
               ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
               if (ret &lt; 0)
               {
                   printf("Failed to copy context from input to output stream codec context\n");
                   goto end;
               }
               out_stream->codec->codec_tag = 0;
               if (ofmt_ctx->oformat->flags &amp; AVFMT_GLOBALHEADER)
                   out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
           }

           //Dump Format------------------
           av_dump_format(ofmt_ctx, 0, out_filename, 1);

           //Open output URL
           if (!(ofmt->flags &amp; AVFMT_NOFILE))
           {
               ret = avio_open(&amp;ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
               if (ret &lt; 0)
               {
                   char strErr[STR_LENGTH_256];
                   av_strerror(AVERROR(ret), strErr, STR_LENGTH_256);
                   CommonGlobalUlti::UltiFunctions::WriteRuntimeLogs("avio_open() " + gcnew String(strErr));
                   printf("Could not open output URL '%s'", out_filename);
                   goto end;
               }
           }
           //Write file header
           ret = avformat_write_header(ofmt_ctx, NULL);
           if (ret &lt; 0)
           {
               char strErr[STR_LENGTH_256];
               av_strerror(AVERROR(ret), strErr, STR_LENGTH_256);
               CommonGlobalUlti::UltiFunctions::WriteRuntimeLogs("avformat_write_header() " + gcnew String(strErr));
               printf("Error occurred when opening output URL\n");
               goto end;
           }

           start_time = av_gettime();
           while (1)
           {
               AVStream *in_stream, *out_stream;
               //Get an AVPacket
               ret = av_read_frame(ifmt_ctx, &amp;pkt);
               if (ret &lt; 0)
                   break;
               //FIX:No PTS (Example: Raw H.264)
               //Simple Write PTS
               if (pkt.pts == AV_NOPTS_VALUE)
               {
                   //Write PTS
                   AVRational time_base1 = ifmt_ctx->streams[videoindex]->time_base;
                   //Duration between 2 frames (us)
                   int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(ifmt_ctx->streams[videoindex]->r_frame_rate);
                   //Parameters
                   pkt.pts = (double)(frame_index*calc_duration) / (double)(av_q2d(time_base1)*AV_TIME_BASE);
                   pkt.dts = pkt.pts;
                   pkt.duration = (double)calc_duration / (double)(av_q2d(time_base1)*AV_TIME_BASE);
               }
               //Important:Delay => ko can sleep khi la Camera, chi can khi File
               if (pkt.stream_index == videoindex)
               {
                   AVRational time_base = ifmt_ctx->streams[videoindex]->time_base;
                   AVRational time_base_q = { 1,AV_TIME_BASE };
                   int64_t pts_time = av_rescale_q(pkt.dts, time_base, time_base_q);
                   int64_t now_time = av_gettime() - start_time;
                   if (pts_time > now_time)
                       av_usleep(pts_time - now_time);
               }

               in_stream = ifmt_ctx->streams[pkt.stream_index];
               out_stream = ofmt_ctx->streams[pkt.stream_index];
               /* copy packet */
               //Convert PTS/DTS
               pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
               pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
               pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
               pkt.pos = -1;
               //Print to Screen
               if (pkt.stream_index == videoindex)
               {
                   printf("Send %8d video frames to output URL\n", frame_index);
                   frame_index++;
               }
               //ret = av_write_frame(ofmt_ctx, &amp;pkt);
               ret = av_interleaved_write_frame(ofmt_ctx, &amp;pkt);
               if (ret &lt; 0)
               {
                   printf("Error muxing packet\n");
                   break;
               }

               av_free_packet(&amp;pkt);

           } //End while (1)

           //Write file trailer
           av_write_trailer(ofmt_ctx);
       end:
           avformat_close_input(&amp;ifmt_ctx);
           /* close output */
           if (ofmt_ctx &amp;&amp; !(ofmt->flags &amp; AVFMT_NOFILE))
               avio_close(ofmt_ctx->pb);
           avformat_free_context(ofmt_ctx);
           if (ret &lt; 0 &amp;&amp; ret != AVERROR_EOF) {
               printf("Error occurred.\n");
               return -1;
           }
           return 0;
       }