Recherche avancée

Médias (2)

Mot : - Tags -/documentation

Autres articles (91)

  • Keeping control of your media in your hands

    13 avril 2011, par

    The vocabulary used on this site and around MediaSPIP in general, aims to avoid reference to Web 2.0 and the companies that profit from media-sharing.
    While using MediaSPIP, you are invited to avoid using words like "Brand", "Cloud" and "Market".
    MediaSPIP is designed to facilitate the sharing of creative media online, while allowing authors to retain complete control of their work.
    MediaSPIP aims to be accessible to as many people as possible and development is based on expanding the (...)

  • Participer à sa traduction

    10 avril 2011

    Vous pouvez nous aider à améliorer les locutions utilisées dans le logiciel ou à traduire celui-ci dans n’importe qu’elle nouvelle langue permettant sa diffusion à de nouvelles communautés linguistiques.
    Pour ce faire, on utilise l’interface de traduction de SPIP où l’ensemble des modules de langue de MediaSPIP sont à disposition. ll vous suffit de vous inscrire sur la liste de discussion des traducteurs pour demander plus d’informations.
    Actuellement MediaSPIP n’est disponible qu’en français et (...)

  • Creating farms of unique websites

    13 avril 2011, par

    MediaSPIP 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" (...)

Sur d’autres sites (20945)

  • 6 Crucial Benefits of Conversion Rate Optimisation

    26 février 2024, par Erin

    Whether investing time or money in marketing, you want the best return on your investment. You want to get as many customers as possible with your budget and resources.

    That’s what conversion rate optimisation (CRO) aims to do. But how does it help you achieve this major goal ? 

    This guide explores the concrete benefits of conversion rate optimisation and how they lead to more effective marketing and ROI. We’ll also introduce specific CRO best practices to help unlock these benefits.

    What is conversion rate optimisation ?

    Conversion rate optimisation (CRO) is the process of examining your website for improvements and creating tests to increase the number of visitors who take a desired action, like purchasing a product or submitting a form.

    The conversion rate is the percentage of visitors who complete a specific goal.

    Illustration of what conversion rate optimisation is

    In order to improve your conversion rate, you need to figure out :

    • Where your customers come from
    • How potential customers navigate or interact with your website
    • Where potential customers are likely to exit your site (or abandon carts)
    • What patterns drive valuable actions like sign-ups and sales

    From there, you can gradually implement changes that will drive more visitors to convert. That’s the essence of conversion rate optimisation.

    6 top benefits of conversion rate optimisation (and best practices to unlock them)

    Conversion rate optimisation can help you get more out of your campaigns without investing more. CRO helps you in these six ways :

    1. Understand your visitors (and customers) better

    The main goal of CRO is to boost conversions, but it’s more than that. In the process of improving conversion rates, you’ll also benefit by gaining deep insights into user behaviour, preferences, and needs. 

    Using web analytics, tests and behavioural analytics, CRO helps marketers shape their website to match what users need.

    Best practices for understanding your customer :

    First, analyse how visitors act with full context (the pages they view, how long they stay and more). 

    In Matomo, you can use the Users Flow report to understand how visitors navigate through your site. This will help you visualise and identify trends in the buyer’s journey.

    User flow chart in Matomo analytics

    Then, you can dive deeper by defining and analysing journeys with Funnels. This shows you how many potential customers follow through each step in your defined journey and identify where you might have a leaky funnel. 

    Goal funnel chart in Matomo analytics

    In the above Funnel Report, nearly half of our visitors, just 44%, are moving forward in the buyer’s journey after landing on our scuba diving mask promotion page. With 56% of potential customers dropping off at this page, it’s a prime opportunity for optimising conversions.

    Think of Funnels as your map, and pages with high drop-off rates as valuable opportunities for improvement.

    Once you notice patterns, you can try to identify the why. Analyse the pages, do user testing and do your best to improve them.

    2. Deliver a better user experience

    A better understanding of your customers’ needs means you can deliver a better user experience.

    Illustration of improving the user experience

    For example, if you notice many people spend more time than expected on a particular step in the sign-up process, you can work to streamline it.

    Best practices for improving your user experience : 

    To do this, you need to come up with testable hypotheses. Start by using Heatmaps and Session Recordings to visualise the user experience and understand where visitors are hesitating, experiencing points of frustration, and exiting. 

    You need to outline what drives certain patterns in behaviour — like cart abandonment for specific products, and what you think can fix them.

    Example of a heatmap in Matomo analytics

    Let’s look at an example. In the screenshot above, we used Matomo’s Heatmap feature to analyse user behaviour on our website. 

    Only 65% of visitors scroll down far enough to encounter our main call to action to “Write a Review.” This insight suggests a potential opportunity for optimisation, where we can focus efforts on encouraging more users to engage with this key element on our site.

    Once you’ve identified an area of improvement, you need to test the results of your proposed solution to the problem. The most common way to do this is with an A/B test. 

    This is a test where you create a new version of the problematic page, trying different titles, comparing long, and short copy, adding or removing images, testing variations of call-to-action buttons and more. Then, you compare the results — the conversion rate — against the original. With Matomo’s A/B Testing feature, you can easily split traffic between the original and one or more variations.

    A/B testing in Matomo analytics

    In the example above from Matomo, we can see that testing different header sizes on a page revealed that the wider header led to a higher conversion rate of 47%, compared to the original rate of 35% and the smaller header’s 36%.

    Matomo’s report also analyses the “statistical significance” of the difference in results. Essentially, this is the likelihood that the difference comes from the changes you made in the variation. With a small sample size, random patterns (like one page receiving more organic search visits) can cause the differences.

    If you see a significant change over a larger sample size, you can be fairly certain that the difference is meaningful. And that’s exactly what a high statistical significance rating indicates in Matomo. 

    Once a winner is identified, you can apply the change and start a new experiment. 

    3. Create a culture of data-driven decision-making

    Marketers can no longer afford to rely on guesswork or gamble away budgets and resources. In our digital age, you must use data to get ahead of the competition. In 2021, 65% of business leaders agreed that decisions were getting more complex.

    CRO is a great way to start a company-wide focus on data-driven decision-making. 

    Best practices to start a data-driven culture :

    Don’t only test “hunches” or “best practices” — look at the data. Figure out the patterns that highlight how different types of visitors interact with your site.

    Try to answer these questions :

    • How do our most valuable customers interact with our site before purchasing ?
    • How do potential customers who abandon their carts act ?
    • Where do our most valuable customers come from ?

    Moreover, it’s key to democratise insights by providing multiple team members access to information, fostering informed decision-making company-wide.

    4. Lower your acquisition costs and get higher ROI from all marketing efforts

    Once you make meaningful optimisations, CRO can help you lower customer acquisition costs (CAC). Getting new customers through advertising will be cheaper.

    As a result, you’ll get a better return on investment (ROI) on all your campaigns. Every ad and dollar invested will get you closer to a new customer than before. That’s the bottom line of CRO.

    Best practices to lower your CAC (customer acquisition costs) through CRO adjustments :

    The easiest way to lower acquisition costs is to understand where your customers come from. Use marketing attribution to track the results of your campaigns, revealing how each touchpoint contributes to conversions and revenue over time, beyond just last-click attribution.

    You can then compare the number of conversions to the marketing costs of each channel, to get a channel-specific breakdown of CAC.

    This performance overview can help you quickly prioritise the best value channels and ads, lowering your CAC. But these are only surface-level insights. 

    You can also further lower CAC by optimising the pages these campaigns send visitors to. Start with a deep dive into your landing pages using features like Matomo’s Session Recordings or Heatmaps.

    They can help you identify issues with an unengaging user experience or content. Using these insights, you can create A/B tests, where you implement a new page that replaces problematic headlines, buttons, copy, or visuals.

    Example of a multivariate test for headlines

    When a test shows a statistically significant improvement in conversion rates, implement the new version. Repeat this over time, and you can increase your conversion rates significantly, getting more customers with the same spend. This will reduce your customer acquisition costs, and help your company grow faster without increasing your ad budget.

    5. Improve your average order value (AOV) and customer lifetime value (CLV)

    CRO isn’t only about increasing the number of customers you convert. If you adapt your approach, you can also use it to increase the revenue from each customer you bring in. 

    But you can’t do that by only tracking conversion rates, you also need to track exactly what your customers buy.

    If you only blindly optimise for CAC, you even risk lowering your CLV and the overall profitability of your campaigns. (For example, if you focus on Facebook Ads with a $6 CAC, but an average CLV of $50, over Google Ads with a $12 CAC, but a $100 CLV.)

    Best practices to track and improve CLV :

    First, integrate your analytics platform with your e-commerce (B2C) or your CRM (B2B). This will help you get a more holistic view of your customers. You don’t want the data to stop at “converted.” You want to be able to dive deep into the patterns of high-value customers.

    The sales report in Matomo’s ecommerce analytics makes it easy to break down average order value by channels, campaigns, and specific ads.

    Ecommerce sales report in Matomo analytics

    In the report above, we can see that search engines drive customers who spend significantly more, on average, than social networks — $241 vs. $184. But social networks drive a higher volume of customers and more revenue.

    To figure out which channel to focus on, you need to see how the CAC compares to the AOV (or CLV for B2B customers). Let’s say the CAC of social networks is $50, while the search engine CAC is $65. Search engine customers are more profitable — $176 vs. $134. So you may want to adjust some more budget to that channel.

    To put it simply :

    Profit per customer = AOV (or CLV) – CAC

    Example :

    • Profit per customer for social networks = $184 – $50 = $134
    • Profit per customer for search engines = $241 – $65 = $176

    You can also try to A/B test changes that may increase the AOV, like creating a product bundle and recommending it on specific sales pages.

    An improvement in CLV will make your campaigns more profitable, and help stretch your advertising budget even further.

    6. Improve your content and SEO rankings

    A valuable side-effect of focusing on CRO metrics and analyses is that it can boost your SEO rankings. 

    How ? 

    CRO helps you improve the user experience of your website. That’s a key signal Google (and other search engines) care about when ranking webpages. 

    Illustration of how better content improves SEO rankings

    For example, Google’s algorithm considers “dwell time,” AKA how long a user stays on your page. If many users quickly return to the results page and click another result, that’s a bad sign. But if most people stay on your site for a while (or don’t return to Google at all), Google thinks your page gives the user their answer.

    As a result, Google will improve your website’s ranking in the search results.

    Best practices to make the most of CRO when it comes to SEO :

    Use A/B Testing, Heatmaps, and Session Recordings to run experiments and understand user behaviour. Test changes to headlines, page layout, imagery and more to see how it impacts the user experience. You can even experiment with completely changing the content on a page, like substituting an introduction.

    Bring your CRO-testing mindset to important pages that aren’t ranking well to improve metrics like dwell time.

    Start optimising your conversion rate today

    As you’ve seen, enjoying the benefits of CRO heavily relies on the data from a reliable web analytics solution. 

    But in an increasingly privacy-conscious world (just look at the timeline of GDPR updates and fines), you must tread carefully. One of the dilemmas that marketing managers face today is whether to prioritise data quality or privacy (and regulations).

    With Matomo, you don’t have to choose. Matomo values both data quality and privacy, adhering to stringent privacy laws like GDPR and CCPA.

    Unlike other web analytics, Matomo doesn’t sample data or use AI and machine learning to fill data gaps. Plus, you can track without annoying visitors with a cookie consent banner – so you capture 100% of traffic while respecting user privacy (excluding in Germany and UK).

    And as you’ve already seen above, you’ll still get plenty of reports and insights to drive your CRO efforts. With User Flows, Funnels, Session Recordings, Form Analytics, and Heatmaps, you can immediately find insights to improve your bottom line.

    And our built-in A/B testing feature will help you test your hypotheses and drive reliable progress. If you’re ready to reliably optimise conversion rates (with accuracy and without privacy concerns), try Matomo for free for 21 days. No credit card required.

  • Protecting consumer privacy : How to ensure CCPA compliance

    18 août 2023, par Erin — CCPA, Privacy

    The California Consumer Privacy Act (CCPA) is a state law that enhances privacy rights and consumer protection for residents of California. 

    It grants consumers six rights, like the right to know what personal information is being collected about them by businesses and others. 

    CCPA also requires businesses to provide notice of data collection practices. Consumers can choose to opt out of the sale of their data. 

    In this article, we’ll learn more about the scope of CCPA, the penalties for non-compliance and how our web analytics tool, Matomo, can help you create a CCPA-compliant framework.

    What is the CCPA ? 

    CCPA was implemented on January 1, 2020. It ensures that businesses securely handle individuals’ personal information and respect their privacy in the digital ecosystem. 

    How does CCPA compliance add value

    CCPA addresses the growing concerns over privacy and data protection ; 40% of US consumers share that they’re worried about digital privacy. With the increasing amount of personal information being collected and shared by businesses, there was a need to establish regulations to provide individuals with more control and transparency over their data. 

    CCPA aims to protect consumer privacy rights and promote greater accountability from businesses when handling personal information.

    Scope of CCPA 

    The scope of CCPA includes for-profit businesses that collect personal information from California residents, regardless of where you run the business from.

    It defines three thresholds that determine the inclusion criteria for businesses subject to CCPA regulations. 

    Businesses need to abide by CCPA if they meet any of the three options :

    1. Revenue threshold : Have an annual gross revenue of over $25 million.
    2. Consumer threshold : Businesses that purchase, sell or distribute the personal information of 100,000 or more consumers, households or devices.
    3. Data threshold : Businesses that earn at least half of their revenue annually from selling the personal information of California residents.

    What are the six consumer rights under the CCPA ? 

    Here’s a short description of the six consumer rights. 

    The six rights of consumers under CCPA
    1. Right to know : Under this right, you can ask a business to disclose specific personal information they collect about you and the categories of sources of the information. You can also know the purpose of collection and to which third-party the business will disclose this info. This allows consumers to understand what information is being held and how it is used. You can request this info for free twice a year.
    2. Right to delete : Consumers can request the deletion of their personal information. Companies must comply with some exceptions.
    3. Right to opt-out : Consumers can deny the sale of their personal information. Companies must provide a link on their homepage for users to exercise this right. After you choose this, companies can’t sell your data unless you authorise them to do so later.
    4. Right to non-discrimination : Consumers cannot be discriminated against for exercising their CCPA rights. For instance, a company cannot charge different prices, provide a different quality of service or deny services.
    5. Right to correct : Consumers can request to correct inaccurate personal information.

    6. Right to limit use : Consumers can specify how they want the businesses to use their sensitive personal information. This includes social security numbers, financial account details, precise geolocation data or genetic data. Consumers can direct businesses to use this sensitive information only for specific purposes, such as providing the requested services.

    Penalties for CCPA non-compliance 

    52% of organisations have yet to adopt CCPA principles as of 2022. Non-compliance can attract penalties.

    Section 1798.155 of the CCPA states that any business that doesn’t comply with CCPA’s terms can face penalties based on the consumer’s private right to action. Consumers can directly take the company to the civil court and don’t need prosecutors’ interventions. 

    Businesses get a chance of 30 days to make amends for their actions. 

    If that’s also not possible, the business may receive a civil penalty of up to $2,500 per violation. Violations can be of any kind, even accidental. An intentional violation can attract a fine of $7,500. 

    Consumers can also initiate private lawsuits to claim damages that range from $100 to $750, or actual damages (whichever is higher), for each occurrence of their unredacted and unencrypted data being breached on a business’s server.

    CCPA vs. GDPR 

    Both CCPA and GDPR aim to enhance individuals’ control over their personal information and provide transparency about how their data is collected, used and shared. The comparison between the CCPA and GDPR is crucial in understanding the regulatory framework of data protection laws.

    Here’s how CCPA and GDPR differ :

    Scope

    • CCPA is for businesses that meet specific criteria and collect personal information from California residents. 
    • GDPR (General Data Protection Regulation) applies to businesses that process the personal data of citizens and residents of the European Union.

    Definition of personal information

    • CCPA includes personal information broadly, including identifiers such as IP addresses and households. Examples include name, email id, location and browsing history. However, it excludes HIPAA-protected medical data, clinical trial data and other personal information from government records.
    • GDPR covers any personal data relating to an identified or identifiable individual, excluding households. Examples include the phone number, email address and personal identification number. It excludes anonymous and deceased person’s data.
    Personal information definition under CCPA and GDPR

    Consent

    • Under the CCPA, consumers can opt out of the sale of their personal information.
    • GDPR states that organisations should obtain explicit consent from individuals for processing their personal data.

    Rights

    • CCPA grants the right to know what personal information is being collected and the right to request deletion of their personal information.
    • GDPR also gives individuals various rights, such as the right to access and rectify their personal data, the right to erasure (also known as the right to be forgotten) and also the right to data portability. 

    Enforcement

    • For CCPA, businesses may have to pay $7,500 for each violation. 
    • GDPR has stricter penalties for non-compliance, with fines of up to 4% of the global annual revenue of a company or €20 million, whichever is higher.

    A 5-step CCPA compliance framework 

    Here’s a simple framework you can follow to ensure compliance with CCPA. Alongside this, we’ll also share how Matomo can help. 

    Matomo is an open-source web analytics platform trusted by organisations like the United Nations, NASA and more. It provides valuable insights into website traffic, visitor behaviour and marketing effectiveness. More than 1 million websites and apps (approximately 1% of the internet !) use our solution, and it’s available in 50+ languages. Below, we’ll share how you can use Matomo to be CCPA compliant.

    1. Assess data

    First, familiarise yourself with the California Consumer Privacy Act and check your eligibility for CCPA compliance. 

    For example, as mentioned earlier, one threshold is : purchases, receives or sells the personal data of 100,000 or more individuals or households

    But how do you know if you have crossed 100K ? With Matomo ! 

    Go to last year’s calendar, select visitors, then go to locations and under the “Region” option, check for California. If you’ve crossed 100K visitors, you know you have to become CCPA compliant.

    View geolocation traffic details in Matomo

    Identify and assess the personal information you collect with Matomo.

    2. Evaluate privacy practices

    Review the current state of your privacy policies and practices. Conduct a thorough assessment of data sharing and third-party agreements. Then, update policies and procedures to align with CCPA requirements.

    For example, you can anonymise IP addresses with Matomo to ensure that user data collected for web analytics purposes cannot be used to trace back to specific individuals.

    Using Matomo to anonymize visitors' IP addresses

    If you have a consent management solution to honour user requests for data privacy, you can also integrate Matomo with it. 

    3. Communicate 

    Inform consumers about their CCPA rights and how you handle their data.

    Establish procedures for handling consumer requests and obtaining consent. For example, you can add an opt-out form on your website with Matomo. Or you can also use Matomo to disable cookies from your website.

    Screenshot of a command line disabling cookies

    Documenting your compliance efforts, including consumer requests and how you responded to them, is a good idea. Finally, educate staff on CCPA compliance and their responsibilities to work collaboratively.

    4. Review vendor contracts

    Assessing vendor contracts allows you to determine if they include necessary data processing agreements. You can also identify if vendors are sharing personal information with third parties, which could pose a compliance risk. Verify if vendors have adequate security measures in place to protect the personal data they handle.

    That’s why you can review and update agreements to include provisions for data protection, privacy and CCPA requirements.

    Establish procedures to monitor and review vendor compliance with CCPA regularly. This may include conducting audits, requesting certifications and implementing controls to mitigate risks associated with vendors handling personal data.

    5. Engage legal counsel

    Consider consulting with legal counsel to ensure complete understanding and compliance with CCPA regulations.

    Finally, stay updated on any changes or developments related to CCPA and adjust your compliance efforts accordingly.

    Matomo and CCPA compliance 

    There’s an increasing emphasis on privacy regulations like CCPA. Matomo offers a robust solution that allows businesses to be CCPA-compliant without sacrificing the ability to track and analyse crucial data.

    You can gain in-depth insights into user behaviour and website performance — all while prioritising data protection and privacy. 

    Request a demo or sign up for a free 21-day trial to get started with our powerful CCPA-compliant web analytics platform — no credit card required. 

    Disclaimer

    We are not lawyers and don’t claim to be. The information provided here is to help give an introduction to CCPA. We encourage every business and website to take data privacy seriously and discuss these issues with your lawyer if you have any concerns.

  • Fragmented MP4 - problem playing in browser

    12 juin 2019, par PookyFan

    I try to create fragmented MP4 from raw H264 video data so I could play it in internet browser’s player. My goal is to create live streaming system, where media server would send fragmented MP4 pieces to browser. The server would buffer input data from RaspberryPi camera, which sends video as H264 frames. It would then mux that video data and make it available for client. The browser would play media data (that were muxed by server and sent i.e. through websocket) by using Media Source Extensions.

    For test purpose I wrote the following pieces of code (using many examples I found in the intenet) :

    C++ application using avcodec which muxes raw H264 video to fragmented MP4 and saves it to a file :

    #define READBUFSIZE 4096
    #define IOBUFSIZE 4096
    #define ERRMSGSIZE 128

    #include <cstdint>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>

    extern "C"
    {
       #include <libavformat></libavformat>avformat.h>
       #include <libavutil></libavutil>error.h>
       #include <libavutil></libavutil>opt.h>
    }

    enum NalType : uint8_t
    {
       //NALs containing stream metadata
       SEQ_PARAM_SET = 0x7,
       PIC_PARAM_SET = 0x8
    };

    std::vector outputData;

    int mediaMuxCallback(void *opaque, uint8_t *buf, int bufSize)
    {
       outputData.insert(outputData.end(), buf, buf + bufSize);
       return bufSize;
    }

    std::string getAvErrorString(int errNr)
    {
       char errMsg[ERRMSGSIZE];
       av_strerror(errNr, errMsg, ERRMSGSIZE);
       return std::string(errMsg);
    }

    int main(int argc, char **argv)
    {
       if(argc &lt; 2)
       {
           std::cout &lt;&lt; "Missing file name" &lt;&lt; std::endl;
           return 1;
       }

       std::fstream file(argv[1], std::ios::in | std::ios::binary);
       if(!file.is_open())
       {
           std::cout &lt;&lt; "Couldn't open file " &lt;&lt; argv[1] &lt;&lt; std::endl;
           return 2;
       }

       std::vector inputMediaData;
       do
       {
           char buf[READBUFSIZE];
           file.read(buf, READBUFSIZE);

           int size = file.gcount();
           if(size > 0)
               inputMediaData.insert(inputMediaData.end(), buf, buf + size);
       } while(!file.eof());
       file.close();

       //Initialize avcodec
       av_register_all();
       uint8_t *ioBuffer;
       AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
       AVCodecContext *codecCtxt = avcodec_alloc_context3(codec);
       AVCodecParserContext *parserCtxt = av_parser_init(AV_CODEC_ID_H264);
       AVOutputFormat *outputFormat = av_guess_format("mp4", nullptr, nullptr);
       AVFormatContext *formatCtxt;
       AVIOContext *ioCtxt;
       AVStream *videoStream;

       int res = avformat_alloc_output_context2(&amp;formatCtxt, outputFormat, nullptr, nullptr);
       if(res &lt; 0)
       {
           std::cout &lt;&lt; "Couldn't initialize format context; the error was: " &lt;&lt; getAvErrorString(res) &lt;&lt; std::endl;
           return 3;
       }

       if((videoStream = avformat_new_stream( formatCtxt, avcodec_find_encoder(formatCtxt->oformat->video_codec) )) == nullptr)
       {
           std::cout &lt;&lt; "Couldn't initialize video stream" &lt;&lt; std::endl;
           return 4;
       }
       else if(!codec)
       {
           std::cout &lt;&lt; "Couldn't initialize codec" &lt;&lt; std::endl;
           return 5;
       }
       else if(codecCtxt == nullptr)
       {
           std::cout &lt;&lt; "Couldn't initialize codec context" &lt;&lt; std::endl;
           return 6;
       }
       else if(parserCtxt == nullptr)
       {
           std::cout &lt;&lt; "Couldn't initialize parser context" &lt;&lt; std::endl;
           return 7;
       }
       else if((ioBuffer = (uint8_t*)av_malloc(IOBUFSIZE)) == nullptr)
       {
           std::cout &lt;&lt; "Couldn't allocate I/O buffer" &lt;&lt; std::endl;
           return 8;
       }
       else if((ioCtxt = avio_alloc_context(ioBuffer, IOBUFSIZE, 1, nullptr, nullptr, mediaMuxCallback, nullptr)) == nullptr)
       {
           std::cout &lt;&lt; "Couldn't initialize I/O context" &lt;&lt; std::endl;
           return 9;
       }

       //Set video stream data
       videoStream->id = formatCtxt->nb_streams - 1;
       videoStream->codec->width = 1280;
       videoStream->codec->height = 720;
       videoStream->time_base.den = 60; //FPS
       videoStream->time_base.num = 1;
       videoStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
       formatCtxt->pb = ioCtxt;

       //Retrieve SPS and PPS for codec extdata
       const uint32_t synchMarker = 0x01000000;
       unsigned int i = 0;
       int spsStart = -1, ppsStart = -1;
       uint16_t spsSize = 0, ppsSize = 0;
       while(spsSize == 0 || ppsSize == 0)
       {
           uint32_t *curr =  (uint32_t*)(inputMediaData.data() + i);
           if(*curr == synchMarker)
           {
               unsigned int currentNalStart = i;
               i += sizeof(uint32_t);
               uint8_t nalType = inputMediaData.data()[i] &amp; 0x1F;
               if(nalType == SEQ_PARAM_SET)
                   spsStart = currentNalStart;
               else if(nalType == PIC_PARAM_SET)
                   ppsStart = currentNalStart;

               if(spsStart >= 0 &amp;&amp; spsSize == 0 &amp;&amp; spsStart != i)
                   spsSize = currentNalStart - spsStart;
               else if(ppsStart >= 0 &amp;&amp; ppsSize == 0 &amp;&amp; ppsStart != i)
                   ppsSize = currentNalStart - ppsStart;
           }
           ++i;
       }

       videoStream->codec->extradata = inputMediaData.data() + spsStart;
       videoStream->codec->extradata_size = ppsStart + ppsSize;

       //Write main header
       AVDictionary *options = nullptr;
       av_dict_set(&amp;options, "movflags", "frag_custom+empty_moov", 0);
       res = avformat_write_header(formatCtxt, &amp;options);
       if(res &lt; 0)
       {
           std::cout &lt;&lt; "Couldn't write container main header; the error was: " &lt;&lt; getAvErrorString(res) &lt;&lt; std::endl;
           return 10;
       }

       //Retrieve frames from input video and wrap them in container
       int currentInputIndex = 0;
       int framesInSecond = 0;
       while(currentInputIndex &lt; inputMediaData.size())
       {
           uint8_t *frameBuffer;
           int frameSize;
           res = av_parser_parse2(parserCtxt, codecCtxt, &amp;frameBuffer, &amp;frameSize, inputMediaData.data() + currentInputIndex,
               inputMediaData.size() - currentInputIndex, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
           if(frameSize == 0) //No more frames while some data still remains (is that even possible?)
           {
               std::cout &lt;&lt; "Some data left unparsed: " &lt;&lt; std::to_string(inputMediaData.size() - currentInputIndex) &lt;&lt; std::endl;
               break;
           }

           //Prepare packet with video frame to be dumped into container
           AVPacket packet;
           av_init_packet(&amp;packet);
           packet.data = frameBuffer;
           packet.size = frameSize;
           packet.stream_index = videoStream->index;
           currentInputIndex += frameSize;

           //Write packet to the video stream
           res = av_write_frame(formatCtxt, &amp;packet);
           if(res &lt; 0)
           {
               std::cout &lt;&lt; "Couldn't write packet with video frame; the error was: " &lt;&lt; getAvErrorString(res) &lt;&lt; std::endl;
               return 11;
           }

           if(++framesInSecond == 60) //We want 1 segment per second
           {
               framesInSecond = 0;
               res = av_write_frame(formatCtxt, nullptr); //Flush segment
           }
       }
       res = av_write_frame(formatCtxt, nullptr); //Flush if something has been left

       //Write media data in container to file
       file.open("my_mp4.mp4", std::ios::out | std::ios::binary);
       if(!file.is_open())
       {
           std::cout &lt;&lt; "Couldn't open output file " &lt;&lt; std::endl;
           return 12;
       }

       file.write((char*)outputData.data(), outputData.size());
       if(file.fail())
       {
           std::cout &lt;&lt; "Couldn't write to file" &lt;&lt; std::endl;
           return 13;
       }

       std::cout &lt;&lt; "Media file muxed successfully" &lt;&lt; std::endl;
       return 0;
    }
    </vector></string></fstream></iostream></cstdint>

    (I hardcoded a few values, such as video dimensions or framerate, but as I said this is just a test code.)


    Simple HTML webpage using MSE to play my fragmented MP4

       


       <video width="1280" height="720" controls="controls">
       </video>

    <code class="echappe-js">&lt;script&gt;<br />
    var vidElement = document.querySelector('video');<br />
    <br />
    if (window.MediaSource) {<br />
     var mediaSource = new MediaSource();<br />
     vidElement.src = URL.createObjectURL(mediaSource);<br />
     mediaSource.addEventListener('sourceopen', sourceOpen);<br />
    } else {<br />
     console.log(&quot;The Media Source Extensions API is not supported.&quot;)<br />
    }<br />
    <br />
    function sourceOpen(e) {<br />
     URL.revokeObjectURL(vidElement.src);<br />
     var mime = 'video/mp4; codecs=&quot;avc1.640028&quot;';<br />
     var mediaSource = e.target;<br />
     var sourceBuffer = mediaSource.addSourceBuffer(mime);<br />
     var videoUrl = 'my_mp4.mp4';<br />
     fetch(videoUrl)<br />
       .then(function(response) {<br />
         return response.arrayBuffer();<br />
       })<br />
       .then(function(arrayBuffer) {<br />
         sourceBuffer.addEventListener('updateend', function(e) {<br />
           if (!sourceBuffer.updating &amp;amp;&amp;amp; mediaSource.readyState === 'open') {<br />
             mediaSource.endOfStream();<br />
           }<br />
         });<br />
         sourceBuffer.appendBuffer(arrayBuffer);<br />
       });<br />
    }<br />
    &lt;/script&gt;

    Output MP4 file generated by my C++ application can be played i.e. in MPC, but it doesn’t play in any web browser I tested it with. It also doesn’t have any duration (MPC keeps showing 00:00).

    To compare output MP4 file I got from my C++ application described above, I also used FFMPEG to create fragmented MP4 file from the same source file with raw H264 stream. I used the following command :

    ffmpeg -r 60 -i input.h264 -c:v copy -f mp4 -movflags empty_moov+default_base_moof+frag_keyframe test.mp4

    This file generated by FFMPEG is played correctly by every web browser I used for tests. It also has correct duration (but also it has trailing atom, which wouldn’t be present in my live stream anyway, and as I need a live stream, it won’t have any fixed duration in the first place).

    MP4 atoms for both files look very similiar (they have identical avcc section for sure). What’s interesting (but not sure if it’s of any importance), both files have different NALs format than input file (RPI camera produces video stream in Annex-B format, while output MP4 files contain NALs in AVCC format... or at least it looks like it’s the case when I compare mdat atoms with input H264 data).

    I assume there is some field (or a few fields) I need to set for avcodec to make it produce video stream that would be properly decoded and played by browsers players. But what field(s) do I need to set ? Or maybe problem lies somewhere else ? I ran out of ideas.


    EDIT 1 :
    As suggested, I investigated binary content of both MP4 files (generated by my app and FFMPEG tool) with hex editor. What I can confirm :

    • both files have identical avcc section (they match perfectly and are in AVCC format, I analyzed it byte after byte and there’s no mistake about it)
    • both files have NALs in AVCC format (I looked closely at mdat atoms and they don’t differ between both MP4 files)

    So I guess there’s nothing wrong with the extradata creation in my code - avcodec takes care of it properly, even if I just feed it with SPS and PPS NALs. It converts them by itself, so no need for me to do it by hand. Still, my original problem remains.

    EDIT 2 : I achieved partial success - MP4 generated by my app now plays in Firefox. I added this line to the code (along with rest of stream initialization) :

    videoStream->codec->time_base = videoStream->time_base;

    So now this section of my code looks like this :

    //Set video stream data
    videoStream->id = formatCtxt->nb_streams - 1;
    videoStream->codec->width = 1280;
    videoStream->codec->height = 720;
    videoStream->time_base.den = 60; //FPS
    videoStream->time_base.num = 1;
    videoStream->codec->time_base = videoStream->time_base;
    videoStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
    formatCtxt->pb = ioCtxt;