Recherche avancée

Médias (91)

Autres articles (112)

  • Personnaliser en ajoutant son logo, sa bannière ou son image de fond

    5 septembre 2013, par

    Certains thèmes prennent en compte trois éléments de personnalisation : l’ajout d’un logo ; l’ajout d’une bannière l’ajout d’une image de fond ;

  • Mise à disposition des fichiers

    14 avril 2011, par

    Par défaut, lors de son initialisation, MediaSPIP ne permet pas aux visiteurs de télécharger les fichiers qu’ils soient originaux ou le résultat de leur transformation ou encodage. Il permet uniquement de les visualiser.
    Cependant, il est possible et facile d’autoriser les visiteurs à avoir accès à ces documents et ce sous différentes formes.
    Tout cela se passe dans la page de configuration du squelette. Il vous faut aller dans l’espace d’administration du canal, et choisir dans la navigation (...)

  • Script d’installation automatique de MediaSPIP

    25 avril 2011, par

    Afin de palier aux difficultés d’installation dues principalement aux dépendances logicielles coté serveur, un script d’installation "tout en un" en bash a été créé afin de faciliter cette étape sur un serveur doté d’une distribution Linux compatible.
    Vous devez bénéficier d’un accès SSH à votre serveur et d’un compte "root" afin de l’utiliser, ce qui permettra d’installer les dépendances. Contactez votre hébergeur si vous ne disposez pas de cela.
    La documentation de l’utilisation du script d’installation (...)

Sur d’autres sites (13237)

  • FFMPEG audio transcoding using libav* libraries

    10 février 2014, par vinvinod

    I am writing an audio transcoding application using ffmpeg libraries.
    Here is my code

       /*
        * File:   main.cpp
        * Author: vinod
        * Compile with "g++ -std=c++11 -o audiotranscode main.cpp -lavformat -lavcodec -lavutil -lavfilter"
        *
        */


       #if !defined PRId64 || PRI_MACROS_BROKEN
       #undef PRId64
       #define PRId64 "lld"
       #endif

       #define __STDC_FORMAT_MACROS

       #ifdef   __cplusplus
       extern "C" {
       #endif

       #include
       #include
       #include <sys></sys>types.h>
       #include
       #include <libavutil></libavutil>imgutils.h>
       #include <libavutil></libavutil>samplefmt.h>
       #include <libavutil></libavutil>frame.h>
       #include <libavutil></libavutil>timestamp.h>
       #include <libavformat></libavformat>avformat.h>
       #include <libavfilter></libavfilter>avfilter.h>
       #include <libavfilter></libavfilter>buffersrc.h>
       #include <libavfilter></libavfilter>buffersink.h>
       #include <libswscale></libswscale>swscale.h>
       #include <libavutil></libavutil>opt.h>

       #ifdef   __cplusplus
       }
       #endif

       #include <iostream>
       using namespace std;

       int select_stream, got_frame, got_packet;

       AVFormatContext *in_fmt_ctx = NULL, *out_fmt_ctx = NULL;
       AVCodec *dec_codec = NULL, * enc_codec = NULL;
       AVStream *audio_st = NULL;
       AVCodecContext *enc_ctx = NULL, *dec_ctx = NULL;

       AVFrame *pFrame = NULL, * pFrameFiltered = NULL;

       AVFilterGraph *filter_graph = NULL;
       AVFilterContext *buffersrc_ctx = NULL;
       AVFilterContext *buffersink_ctx = NULL;

       AVPacket packet;

       string inFileName = "/home/vinod/vinod/Media/univac.webm";
       string outFileName = "audio_extracted.m4a";

       int target_bit_rate = 128000,
           sample_rate = 22050,
           channels = 1;
       AVSampleFormat sample_fmt = AV_SAMPLE_FMT_S16;
       string filter_description = "aresample=22050,aformat=sample_fmts=s16:channel_layouts=mono";

       int log_averror(int errcode)
       {
               char *errbuf = (char *) calloc(AV_ERROR_MAX_STRING_SIZE, sizeof(char));
               av_strerror(errcode, errbuf, AV_ERROR_MAX_STRING_SIZE);
               std::cout &lt;&lt; "Error - " &lt;&lt; errbuf &lt;&lt; std::endl;
               delete [] errbuf;
               return -1;
       }

       /**
        * Initialize conversion filter */
       int initialize_audio_filter()
       {
               char args[512];
               int ret;
               AVFilter *buffersrc = avfilter_get_by_name("abuffer");
               AVFilter *buffersink = avfilter_get_by_name("abuffersink");
               AVFilterInOut *outputs = avfilter_inout_alloc();
               AVFilterInOut *inputs = avfilter_inout_alloc();
               filter_graph = avfilter_graph_alloc();
               const enum AVSampleFormat out_sample_fmts[] = {sample_fmt, AV_SAMPLE_FMT_NONE};
               const int64_t out_channel_layouts[] = {av_get_default_channel_layout(out_fmt_ctx -> streams[0] -> codec -> channels), -1};
               const int out_sample_rates[] = {out_fmt_ctx -> streams[0] -> codec -> sample_rate, -1};

               if (!dec_ctx->channel_layout)
                       dec_ctx->channel_layout = av_get_default_channel_layout(dec_ctx->channels);

               snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%" PRIx64,
                        in_fmt_ctx -> streams[select_stream] -> time_base.num, in_fmt_ctx -> streams[select_stream] -> time_base.den,
                        dec_ctx->sample_rate,
                        av_get_sample_fmt_name(dec_ctx->sample_fmt),
                        dec_ctx->channel_layout);
               ret = avfilter_graph_create_filter(&amp;buffersrc_ctx, buffersrc, "in", args, NULL, filter_graph);

               if (ret &lt; 0) {
                       av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
                       return -1;
               }

               ret = avfilter_graph_create_filter(&amp;buffersink_ctx, buffersink, "out", NULL, NULL, filter_graph);

               if (ret &lt; 0) {
                       av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
                       return ret;
               }

               ret = av_opt_set_int_list(buffersink_ctx, "sample_fmts", out_sample_fmts, -1,
                                         AV_OPT_SEARCH_CHILDREN);

               if (ret &lt; 0) {
                       av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n");
                       return ret;
               }

               ret = av_opt_set_int_list(buffersink_ctx, "channel_layouts", out_channel_layouts, -1,
                                         AV_OPT_SEARCH_CHILDREN);

               if (ret &lt; 0) {
                       av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n");
                       return ret;
               }

               ret = av_opt_set_int_list(buffersink_ctx, "sample_rates", out_sample_rates, -1,
                                         AV_OPT_SEARCH_CHILDREN);

               if (ret &lt; 0) {
                       av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n");
                       return ret;
               }

               /* Endpoints for the filter graph. */
               outputs -> name = av_strdup("in");
               outputs -> filter_ctx = buffersrc_ctx;
               outputs -> pad_idx = 0;
               outputs -> next = NULL;
               /* Endpoints for the filter graph. */
               inputs -> name = av_strdup("out");
               inputs -> filter_ctx = buffersink_ctx;
               inputs -> pad_idx = 0;
               inputs -> next = NULL;
               string filter_desc = filter_description;

               if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_desc.c_str(), &amp;inputs, &amp;outputs, NULL)) &lt; 0) {
                       log_averror(ret);
                       exit(1);
               }

               if ((ret = avfilter_graph_config(filter_graph, NULL)) &lt; 0) {
                       log_averror(ret);
                       exit(1);
               }

               /* Print summary of the sink buffer
                * Note: args buffer is reused to store channel layout string */
               AVFilterLink *outlink = buffersink_ctx->inputs[0];
               av_get_channel_layout_string(args, sizeof(args), -1, outlink->channel_layout);
               av_log(NULL, AV_LOG_INFO, "Output: srate:%dHz fmt:%s chlayout:%s\n",
                      (int) outlink->sample_rate,
                      (char *) av_x_if_null(av_get_sample_fmt_name((AVSampleFormat) outlink->format), "?"),
                      args);
               return 0;
       }

       /*
        *
        */
       int main(int argc, char **argv)
       {
               int ret;
               cout &lt;&lt; "Hello World" &lt;&lt; endl;
               printf("abcd");
               avcodec_register_all();
               av_register_all();
               avfilter_register_all();

               /* open input file, and allocate format context */
               if (avformat_open_input(&amp;in_fmt_ctx, inFileName.c_str(), NULL, NULL) &lt; 0) {
                       std::cout &lt;&lt; "error opening input file - " &lt;&lt; inFileName &lt;&lt; std::endl;
                       return -1;
               }

               /* retrieve stream information */
               if (avformat_find_stream_info(in_fmt_ctx, NULL) &lt; 0) {
                       std::cerr &lt;&lt; "Could not find stream information in the input file " &lt;&lt; inFileName &lt;&lt; std::endl;
               }

               /* Dump format details */
               printf("\n ---------------------------------------------------------------------- \n");
               av_dump_format(in_fmt_ctx, 0, inFileName.c_str(), 0);
               printf("\n ---------------------------------------------------------------------- \n");
               /* Choose a audio stream */
               select_stream = av_find_best_stream(in_fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &amp;dec_codec, 0);

               if (select_stream == AVERROR_STREAM_NOT_FOUND) {
                       std::cerr &lt;&lt; "No audio stream found" &lt;&lt; std::endl;
                       return -1;
               }

               if (select_stream == AVERROR_DECODER_NOT_FOUND) {
                       std::cerr &lt;&lt; "No suitable decoder found" &lt;&lt; std::endl;
                       return -1;
               }

               dec_ctx = in_fmt_ctx -> streams[ select_stream] -> codec;
               av_opt_set_int(dec_ctx, "refcounted_frames", 1, 0);

               /* init the audio decoder */
               if ((ret = avcodec_open2(dec_ctx, dec_codec, NULL)) &lt; 0) {
                       av_log(NULL, AV_LOG_ERROR, "Cannot open audio decoder\n");
                       return ret;
               }

               /* allocate output context */
               ret = avformat_alloc_output_context2(&amp;out_fmt_ctx, NULL, NULL,
                                                    outFileName.c_str());

               if (ret &lt; 0) {
                       std::cerr &lt;&lt; "Could not create output context for the file " &lt;&lt; outFileName &lt;&lt; std::endl;
                       return -1;
               }

               /* find the encoder */
               enum AVCodecID codec_id = out_fmt_ctx -> oformat -> audio_codec;
               enc_codec = avcodec_find_encoder(codec_id);

               if (!(enc_codec)) {
                       std::cerr &lt;&lt; "Could not find encoder for - " &lt;&lt; avcodec_get_name(codec_id) &lt;&lt; std::endl;
                       return -1;
               }

               /* add a new stream */
               audio_st = avformat_new_stream(out_fmt_ctx, enc_codec);

               if (!audio_st) {
                       std::cerr &lt;&lt; "Could not add audio stream - " &lt;&lt; std::endl;
               }

               /* Initialise audio codec */
               audio_st -> id = out_fmt_ctx -> nb_streams - 1;
               enc_ctx = audio_st -> codec;
               enc_ctx -> codec_id = codec_id;
               enc_ctx -> codec_type = AVMEDIA_TYPE_AUDIO;
               enc_ctx -> bit_rate = target_bit_rate;
               enc_ctx -> sample_rate = sample_rate;
               enc_ctx -> sample_fmt = sample_fmt;
               enc_ctx -> channels = channels;
               enc_ctx -> channel_layout = av_get_default_channel_layout(enc_ctx -> channels);

               /* Some formats want stream headers to be separate. */
               if (out_fmt_ctx -> oformat -> flags &amp; AVFMT_GLOBALHEADER) {
                       enc_ctx -> flags |= CODEC_FLAG_GLOBAL_HEADER;
               }

               ret = avcodec_open2(out_fmt_ctx -> streams[0] -> codec, enc_codec, NULL);

               if (ret &lt; 0) {
                       std::cerr &lt;&lt; "Could not create codec context for the file " &lt;&lt; outFileName &lt;&lt; std::endl;
                       return -1;
               }

               /* Initialize filter */
               initialize_audio_filter();

               if (!(out_fmt_ctx -> oformat -> flags &amp; AVFMT_NOFILE)) {
                       int ret = avio_open(&amp; out_fmt_ctx -> pb, outFileName.c_str(),
                                           AVIO_FLAG_WRITE);

                       if (ret &lt; 0) {
                               log_averror(ret);
                               return -1;
                       }
               }

               /* Write header */
               if (avformat_write_header(out_fmt_ctx, NULL) &lt; 0) {
                       if (ret &lt; 0) {
                               log_averror(ret);
                               return -1;
                       }
               }

               /* Allocate frame */
               pFrame = av_frame_alloc();

               if (!pFrame) {
                       std::cerr &lt;&lt; "Could not allocate frame\n";
                       return -1;
               }

               pFrameFiltered = av_frame_alloc();

               if (!pFrameFiltered) {
                       std::cerr &lt;&lt; "Could not allocate frame\n";
                       return -1;
               }

               av_init_packet(&amp;packet);
               packet.data = NULL;
               packet.size = 0;

               /* Read packet from the stream */
               while (av_read_frame(in_fmt_ctx, &amp;packet) >= 0) {
                       if (packet.stream_index == select_stream) {
                               avcodec_get_frame_defaults(pFrame);
                               ret = avcodec_decode_audio4(dec_ctx, pFrame, &amp;got_frame, &amp;packet);

                               if (ret &lt; 0) {
                                       log_averror(ret);
                                       return ret;
                               }

                               printf("Decoded packet pts : %ld ", packet.pts);
                               printf("Frame Best Effor pts : %ld \n", pFrame->best_effort_timestamp);
                               /* Set frame pts */
                               pFrame -> pts = av_frame_get_best_effort_timestamp(pFrame);

                               if (got_frame) {
                                       /* push the decoded frame into the filtergraph */
                                       ret = av_buffersrc_add_frame_flags(buffersrc_ctx, pFrame, AV_BUFFERSRC_FLAG_KEEP_REF);

                                       if (ret &lt; 0) {
                                               log_averror(ret);
                                               return ret;
                                       }

                                       /* pull filtered frames from the filtergraph */
                                       while (1) {
                                               ret = av_buffersink_get_frame(buffersink_ctx, pFrameFiltered);

                                               if ((ret == AVERROR(EAGAIN)) || (ret == AVERROR_EOF)) {
                                                       break;
                                               }

                                               if (ret &lt; 0) {
                                                       printf("Error while getting filtered frames from filtergraph\n");
                                                       log_averror(ret);
                                                       return -1;
                                               }

                                               /* Initialize the packets */
                                               AVPacket encodedPacket = {0};
                                               av_init_packet(&amp;encodedPacket);
                                               ret = avcodec_encode_audio2(out_fmt_ctx -> streams[0] -> codec, &amp;encodedPacket, pFrameFiltered, &amp;got_packet);

                                               if (!ret &amp;&amp; got_packet &amp;&amp; encodedPacket.size) {
                                                       /* Set correct pts and dts */
                                                       if (encodedPacket.pts != AV_NOPTS_VALUE) {
                                                               encodedPacket.pts = av_rescale_q(encodedPacket.pts, buffersink_ctx -> inputs[0] -> time_base,
                                                                                                out_fmt_ctx -> streams[0] -> time_base);
                                                       }

                                                       if (encodedPacket.dts != AV_NOPTS_VALUE) {
                                                               encodedPacket.dts = av_rescale_q(encodedPacket.dts, buffersink_ctx -> inputs[0] -> time_base,
                                                                                                out_fmt_ctx -> streams[0] -> time_base);
                                                       }

                                                       printf("Encoded packet pts %ld\n", encodedPacket.pts);
                                                       /* Write the compressed frame to the media file. */
                                                       ret = av_interleaved_write_frame(out_fmt_ctx, &amp;encodedPacket);

                                                       if (ret &lt; 0) {
                                                               log_averror(ret);
                                                               return -1;
                                                       }
                                               } else if (ret &lt; 0) {
                                                       log_averror(ret);
                                                       return -1;
                                               }

                                               av_frame_unref(pFrameFiltered);
                                       }

                                       av_frame_unref(pFrame);
                               }
                       }
               }

               /* Flush delayed frames from encoder*/
               got_packet=1;
               while (got_packet) {
                       AVPacket encodedPacket = {0};
                       av_init_packet(&amp;encodedPacket);
                       ret = avcodec_encode_audio2(out_fmt_ctx -> streams[0] -> codec, &amp;encodedPacket, NULL, &amp;got_packet);

                       if (!ret &amp;&amp; got_packet &amp;&amp; encodedPacket.size) {
                               /* Set correct pts and dts */
                               if (encodedPacket.pts != AV_NOPTS_VALUE) {
                                       encodedPacket.pts = av_rescale_q(encodedPacket.pts, buffersink_ctx -> inputs[0] -> time_base,
                                                                        out_fmt_ctx -> streams[0] -> time_base);
                               }

                               if (encodedPacket.dts != AV_NOPTS_VALUE) {
                                       encodedPacket.dts = av_rescale_q(encodedPacket.dts, buffersink_ctx -> inputs[0] -> time_base,
                                                                        out_fmt_ctx -> streams[0] -> time_base);
                               }

                               printf("Encoded packet pts %ld\n", encodedPacket.pts);
                               /* Write the compressed frame to the media file. */
                               ret = av_interleaved_write_frame(out_fmt_ctx, &amp;encodedPacket);

                               if (ret &lt; 0) {
                                       log_averror(ret);
                                       return -1;
                               }
                       } else if (ret &lt; 0) {
                               log_averror(ret);
                               return -1;
                       }
               }

               /* Write Trailer */
               av_write_trailer(out_fmt_ctx);
               avfilter_graph_free(&amp;filter_graph);

               if (dec_ctx)
                       avcodec_close(dec_ctx);

               avformat_close_input(&amp;in_fmt_ctx);
               av_frame_free(&amp;pFrame);
               av_frame_free(&amp;pFrameFiltered);

               if (!(out_fmt_ctx -> oformat -> flags &amp; AVFMT_NOFILE))
                       avio_close(out_fmt_ctx -> pb);
               avcodec_close(out_fmt_ctx->streams[0]->codec);
               avformat_free_context(out_fmt_ctx);
               return 0;
       }
    </iostream>

    The audio file after transcoding is same duration as the input. But its completely noisy. Can somebody tell me what I am doing wrong here !

  • Can't write RGB frames to mp4 video with FFMPEG

    22 mai 2013, par Michael IV

    I am writing RGB frames to mp4 (h264) using FFMPEG.
    The resulting video is created with the correct length but the visual is completely screwed :
    enter image description here

    My whole setup is based on this tutorial.But there is one difference.In the tutorial YUV frame is written explicitly with some random pixels while in my case I need to convert RGB frame (input) to YUV frame (output) before processing the encoding.

    I am doing it like this :

    The method is called on each frame :

    void  write_video_frame(AVFormatContext *oc, AVStream *st ,uint8_t* data)
    {
       int ret;

       AVCodecContext *c = st->codec;
       if (frame_count >= STREAM_NB_FRAMES) {
           /* No more frames to compress. The codec has a latency of a few
           * frames if using B-frames, so we get the last frames by
           * passing the same picture again. */
       } else {


       sws_ctx =  sws_getContext(c->width, c->height, AV_PIX_FMT_RGB24,c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);
                 avpicture_fill((AVPicture*)&amp;src_picture,data,AV_PIX_FMT_RGB24 , c->width , c->height );
               avpicture_fill((AVPicture*)&amp;dst_picture,outPicture,AV_PIX_FMT_YUV420P , c->width , c->height );

       sws_scale(sws_ctx, src_picture.data, src_picture.linesize, 0,  c->height, dst_picture.data, dst_picture.linesize);




       }

       if (oc->oformat->flags &amp; AVFMT_RAWPICTURE) {
           //// Raw video case - directly store the picture in the packet///
           AVPacket pkt;
           av_init_packet(&amp;pkt);
           pkt.flags        |= AV_PKT_FLAG_KEY;
           pkt.stream_index  = st->index;
           pkt.data          = dst_picture.data[0];
           pkt.size          = sizeof(AVPicture);
           ret = av_interleaved_write_frame(oc, &amp;pkt);
       } else {
           AVPacket pkt = { 0 };
           int got_packet;
           av_init_packet(&amp;pkt);
           // encode the image //
           ret = avcodec_encode_video2(c, &amp;pkt, frame, &amp;got_packet);
           if (ret &lt; 0) {
               //   fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
               exit(1);
           }
           // If size is zero, it means the image was buffered.//
           if (!ret &amp;&amp; got_packet &amp;&amp; pkt.size) {
               pkt.stream_index = st->index;
               // Write the compressed frame to the media file.//
               ret = av_interleaved_write_frame(oc, &amp;pkt);
           } else {
               ret = 0;
           }
       }
       if (ret != 0) {
           //  fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret));
           exit(1);
       }

       frame_count++;
    }

    So what I am doing is getting conversion context.Then filling one picture with RGB24 pixels and setting destination picture empty (dst_picture) to receive converted frame in AV_PIX_FMT_YUV420P format. Then I scale it.
    The FFMPEG throws no errors.

    There is a workaround which works but creates very large output (that is why I don't want to use it.That's if I convert RGB frame explicitly and fetch it directly into destination picture directly like this :

    Bitmap2Yuv420p_calc2Fast(dst_picture.data[0] , data , c->width ,c ->height);

    Where Bitmap2Yuv420p_calc2Fast() looks like this :

    void Bitmap2Yuv420p_calc2Fast(uint8_t *destination, uint8_t *rgb, size_t width, size_t height)

    size_t image_size = width * height ;
    size_t upos = image_size ;
    size_t vpos = upos + upos / 4 ;
    size_t i = 0 ;

       for( size_t line = 0; line &lt; height; ++line )
       {
           if( !(line % 2) )
           {
               for( size_t x = 0; x &lt; width; x += 2 )
               {
                   uint8_t r = rgb[3 * i];
                   uint8_t g = rgb[3 * i + 1];
                   uint8_t b = rgb[3 * i + 2];

                   destination[i++] = ((66*r + 129*g + 25*b) >> 8) + 16;

                   destination[upos++] = ((-38*r + -74*g + 112*b) >> 8) + 128;
                   destination[vpos++] = ((112*r + -94*g + -18*b) >> 8) + 128;

                   r = rgb[3 * i];
                   g = rgb[3 * i + 1];
                   b = rgb[3 * i + 2];

                   destination[i++] = ((66*r + 129*g + 25*b) >> 8) + 16;
               }
           }
           else
           {
               for( size_t x = 0; x &lt; width; x += 1 )
               {
                   uint8_t r = rgb[3 * i];
                   uint8_t g = rgb[3 * i + 1];
                   uint8_t b = rgb[3 * i + 2];

                   destination[i++] = ((66*r + 129*g + 25*b) >> 8) + 16;
               }
           }
       }
    }

    Where is my mistake ?

  • Revision ad484fc6be : Add support for armv7-win32-vs11 The arm assembly files are named .s after conv

    18 mai 2013, par Martin Storsjo

    Changed Paths :
     Add /build/arm-msvs/obj_int_extract.bat


     Modify /build/make/Makefile


     Modify /build/make/configure.sh


     Modify /build/make/gen_msvs_vcxproj.sh


     Modify /configure


     Modify /libs.mk



    Add support for armv7-win32-vs11

    The arm assembly files are named .s after conversion, to reuse
    as much of the existing makefile infrastructure for conversion to
    gas format as possible. Within the generated visual studio project,
    only the converted assembly sources are available, which might not
    be optimal for actually developing it, but is acceptable for
    just building the library.

    Multithreading is disabled since the traditional win32 threading
    functions aren't available on WinRT/Windows Phone 8.

    Building of vpx itself and the examples succeed, while building the
    tests fail due to them using functions not available in the
    windows store/windows phone API subsets - therefore the unit tests
    are disabled.

    This works for building in Visual Studio Express 2012 for Windows
    Phone, while Visual Studio Express 2012 for Windows 8 (for
    "Windows Store" apps) seems to reject the vcxproj files due to
    not supporting "classic style native application or managed
    projects". The built static library should be compatible with that
    platform though.

    Change-Id : Idcd7eca60bfaaaeb09392a9cd7a02e4a670e3b30