
Recherche avancée
Autres articles (87)
-
Personnaliser en ajoutant son logo, sa bannière ou son image de fond
5 septembre 2013, parCertains 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 ;
-
Publier sur MédiaSpip
13 juin 2013Puis-je poster des contenus à partir d’une tablette Ipad ?
Oui, si votre Médiaspip installé est à la version 0.2 ou supérieure. Contacter au besoin l’administrateur de votre MédiaSpip pour le savoir -
Les autorisations surchargées par les plugins
27 avril 2010, parMediaspip core
autoriser_auteur_modifier() afin que les visiteurs soient capables de modifier leurs informations sur la page d’auteurs
Sur d’autres sites (15984)
-
Why does adding audio stream to ffmpeg's libavcodec output container cause a crash ?
29 mars 2021, par SniggerfardimungusAs it stands, my project correctly uses libavcodec to decode a video, where each frame is manipulated (it doesn't matter how) and output to a new video. I've cobbled this together from examples found online, and it works. The result is a perfect .mp4 of the manipulated frames, minus the audio.


My problem is, when I try to add an audio stream to the output container, I get a crash in mux.c that I can't explain. It's in
static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket *pkt)
. Wherest->internal->priv_pts->val = pkt->dts;
is attempted,priv_pts
is nullptr.

I don't recall the version number, but this is from a November 4, 2020 ffmpeg build from git.


My
MediaContentMgr
is much bigger than what I have here. I'm stripping out everything to do with the frame manipulation, so if I'm missing anything, please let me know and I'll edit.

The code that, when added, triggers the nullptr exception, is called out inline


The .h :


#ifndef _API_EXAMPLE_H
#define _API_EXAMPLE_H

#include <glad></glad>glad.h>
#include <glfw></glfw>glfw3.h>
#include "glm/glm.hpp"

extern "C" {
#include <libavcodec></libavcodec>avcodec.h>
#include <libavformat></libavformat>avformat.h>
#include <libavutil></libavutil>avutil.h>
#include <libavutil></libavutil>opt.h>
#include <libswscale></libswscale>swscale.h>
}

#include "shader_s.h"

class MediaContainerMgr {
public:
 MediaContainerMgr(const std::string& infile, const std::string& vert, const std::string& frag, 
 const glm::vec3* extents);
 ~MediaContainerMgr();
 void render();
 bool recording() { return m_recording; }

 // Major thanks to "shi-yan" who helped make this possible:
 // https://github.com/shi-yan/videosamples/blob/master/libavmp4encoding/main.cpp
 bool init_video_output(const std::string& video_file_name, unsigned int width, unsigned int height);
 bool output_video_frame(uint8_t* buf);
 bool finalize_output();

private:
 AVFormatContext* m_format_context;
 AVCodec* m_video_codec;
 AVCodec* m_audio_codec;
 AVCodecParameters* m_video_codec_parameters;
 AVCodecParameters* m_audio_codec_parameters;
 AVCodecContext* m_codec_context;
 AVFrame* m_frame;
 AVPacket* m_packet;
 uint32_t m_video_stream_index;
 uint32_t m_audio_stream_index;
 
 void init_rendering(const glm::vec3* extents);
 int decode_packet();

 // For writing the output video:
 void free_output_assets();
 bool m_recording;
 AVOutputFormat* m_output_format;
 AVFormatContext* m_output_format_context;
 AVCodec* m_output_video_codec;
 AVCodecContext* m_output_video_codec_context;
 AVFrame* m_output_video_frame;
 SwsContext* m_output_scale_context;
 AVStream* m_output_video_stream;
 
 AVCodec* m_output_audio_codec;
 AVStream* m_output_audio_stream;
 AVCodecContext* m_output_audio_codec_context;
};

#endif



And, the hellish .cpp :


#include 
#include 
#include 
#include 
#include 

#include "media_container_manager.h"

MediaContainerMgr::MediaContainerMgr(const std::string& infile, const std::string& vert, const std::string& frag,
 const glm::vec3* extents) :
 m_video_stream_index(-1),
 m_audio_stream_index(-1),
 m_recording(false),
 m_output_format(nullptr),
 m_output_format_context(nullptr),
 m_output_video_codec(nullptr),
 m_output_video_codec_context(nullptr),
 m_output_video_frame(nullptr),
 m_output_scale_context(nullptr),
 m_output_video_stream(nullptr)
{
 // AVFormatContext holds header info from the format specified in the container:
 m_format_context = avformat_alloc_context();
 if (!m_format_context) {
 throw "ERROR could not allocate memory for Format Context";
 }
 
 // open the file and read its header. Codecs are not opened here.
 if (avformat_open_input(&m_format_context, infile.c_str(), NULL, NULL) != 0) {
 throw "ERROR could not open input file for reading";
 }

 printf("format %s, duration %lldus, bit_rate %lld\n", m_format_context->iformat->name, m_format_context->duration, m_format_context->bit_rate);
 //read avPackets (?) from the avFormat (?) to get stream info. This populates format_context->streams.
 if (avformat_find_stream_info(m_format_context, NULL) < 0) {
 throw "ERROR could not get stream info";
 }

 for (unsigned int i = 0; i < m_format_context->nb_streams; i++) {
 AVCodecParameters* local_codec_parameters = NULL;
 local_codec_parameters = m_format_context->streams[i]->codecpar;
 printf("AVStream->time base before open coded %d/%d\n", m_format_context->streams[i]->time_base.num, m_format_context->streams[i]->time_base.den);
 printf("AVStream->r_frame_rate before open coded %d/%d\n", m_format_context->streams[i]->r_frame_rate.num, m_format_context->streams[i]->r_frame_rate.den);
 printf("AVStream->start_time %" PRId64 "\n", m_format_context->streams[i]->start_time);
 printf("AVStream->duration %" PRId64 "\n", m_format_context->streams[i]->duration);
 printf("duration(s): %lf\n", (float)m_format_context->streams[i]->duration / m_format_context->streams[i]->time_base.den * m_format_context->streams[i]->time_base.num);
 AVCodec* local_codec = NULL;
 local_codec = avcodec_find_decoder(local_codec_parameters->codec_id);
 if (local_codec == NULL) {
 throw "ERROR unsupported codec!";
 }

 if (local_codec_parameters->codec_type == AVMEDIA_TYPE_VIDEO) {
 if (m_video_stream_index == -1) {
 m_video_stream_index = i;
 m_video_codec = local_codec;
 m_video_codec_parameters = local_codec_parameters;
 }
 m_height = local_codec_parameters->height;
 m_width = local_codec_parameters->width;
 printf("Video Codec: resolution %dx%d\n", m_width, m_height);
 }
 else if (local_codec_parameters->codec_type == AVMEDIA_TYPE_AUDIO) {
 if (m_audio_stream_index == -1) {
 m_audio_stream_index = i;
 m_audio_codec = local_codec;
 m_audio_codec_parameters = local_codec_parameters;
 }
 printf("Audio Codec: %d channels, sample rate %d\n", local_codec_parameters->channels, local_codec_parameters->sample_rate);
 }

 printf("\tCodec %s ID %d bit_rate %lld\n", local_codec->name, local_codec->id, local_codec_parameters->bit_rate);
 }

 m_codec_context = avcodec_alloc_context3(m_video_codec);
 if (!m_codec_context) {
 throw "ERROR failed to allocate memory for AVCodecContext";
 }

 if (avcodec_parameters_to_context(m_codec_context, m_video_codec_parameters) < 0) {
 throw "ERROR failed to copy codec params to codec context";
 }

 if (avcodec_open2(m_codec_context, m_video_codec, NULL) < 0) {
 throw "ERROR avcodec_open2 failed to open codec";
 }

 m_frame = av_frame_alloc();
 if (!m_frame) {
 throw "ERROR failed to allocate AVFrame memory";
 }

 m_packet = av_packet_alloc();
 if (!m_packet) {
 throw "ERROR failed to allocate AVPacket memory";
 }
}

MediaContainerMgr::~MediaContainerMgr() {
 avformat_close_input(&m_format_context);
 av_packet_free(&m_packet);
 av_frame_free(&m_frame);
 avcodec_free_context(&m_codec_context);


 glDeleteVertexArrays(1, &m_VAO);
 glDeleteBuffers(1, &m_VBO);
}


bool MediaContainerMgr::advance_frame() {
 while (true) {
 if (av_read_frame(m_format_context, m_packet) < 0) {
 // Do we actually need to unref the packet if it failed?
 av_packet_unref(m_packet);
 continue;
 //return false;
 }
 else {
 if (m_packet->stream_index == m_video_stream_index) {
 //printf("AVPacket->pts %" PRId64 "\n", m_packet->pts);
 int response = decode_packet();
 av_packet_unref(m_packet);
 if (response != 0) {
 continue;
 //return false;
 }
 return true;
 }
 else {
 printf("m_packet->stream_index: %d\n", m_packet->stream_index);
 printf(" m_packet->pts: %lld\n", m_packet->pts);
 printf(" mpacket->size: %d\n", m_packet->size);
 if (m_recording) {
 int err = 0;
 //err = avcodec_send_packet(m_output_video_codec_context, m_packet);
 printf(" encoding error: %d\n", err);
 }
 }
 }

 // We're done with the packet (it's been unpacked to a frame), so deallocate & reset to defaults:
/*
 if (m_frame == NULL)
 return false;

 if (m_frame->data[0] == NULL || m_frame->data[1] == NULL || m_frame->data[2] == NULL) {
 printf("WARNING: null frame data");
 continue;
 }
*/
 }
}

int MediaContainerMgr::decode_packet() {
 // Supply raw packet data as input to a decoder
 // https://ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga58bc4bf1e0ac59e27362597e467efff3
 int response = avcodec_send_packet(m_codec_context, m_packet);

 if (response < 0) {
 char buf[256];
 av_strerror(response, buf, 256);
 printf("Error while receiving a frame from the decoder: %s\n", buf);
 return response;
 }

 // Return decoded output data (into a frame) from a decoder
 // https://ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga11e6542c4e66d3028668788a1a74217c
 response = avcodec_receive_frame(m_codec_context, m_frame);
 if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
 return response;
 } else if (response < 0) {
 char buf[256];
 av_strerror(response, buf, 256);
 printf("Error while receiving a frame from the decoder: %s\n", buf);
 return response;
 } else {
 printf(
 "Frame %d (type=%c, size=%d bytes) pts %lld key_frame %d [DTS %d]\n",
 m_codec_context->frame_number,
 av_get_picture_type_char(m_frame->pict_type),
 m_frame->pkt_size,
 m_frame->pts,
 m_frame->key_frame,
 m_frame->coded_picture_number
 );
 }
 return 0;
}


bool MediaContainerMgr::init_video_output(const std::string& video_file_name, unsigned int width, unsigned int height) {
 if (m_recording)
 return true;
 m_recording = true;

 advance_to(0L); // I've deleted the implmentation. Just seeks to beginning of vid. Works fine.

 if (!(m_output_format = av_guess_format(nullptr, video_file_name.c_str(), nullptr))) {
 printf("Cannot guess output format.\n");
 return false;
 }

 int err = avformat_alloc_output_context2(&m_output_format_context, m_output_format, nullptr, video_file_name.c_str());
 if (err < 0) {
 printf("Failed to allocate output context.\n");
 return false;
 }

 //TODO(P0): Break out the video and audio inits into their own methods.
 m_output_video_codec = avcodec_find_encoder(m_output_format->video_codec);
 if (!m_output_video_codec) {
 printf("Failed to create video codec.\n");
 return false;
 }
 m_output_video_stream = avformat_new_stream(m_output_format_context, m_output_video_codec);
 if (!m_output_video_stream) {
 printf("Failed to find video format.\n");
 return false;
 } 
 m_output_video_codec_context = avcodec_alloc_context3(m_output_video_codec);
 if (!m_output_video_codec_context) {
 printf("Failed to create video codec context.\n");
 return(false);
 }
 m_output_video_stream->codecpar->codec_id = m_output_format->video_codec;
 m_output_video_stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
 m_output_video_stream->codecpar->width = width;
 m_output_video_stream->codecpar->height = height;
 m_output_video_stream->codecpar->format = AV_PIX_FMT_YUV420P;
 // Use the same bit rate as the input stream.
 m_output_video_stream->codecpar->bit_rate = m_format_context->streams[m_video_stream_index]->codecpar->bit_rate;
 m_output_video_stream->avg_frame_rate = m_format_context->streams[m_video_stream_index]->avg_frame_rate;
 avcodec_parameters_to_context(m_output_video_codec_context, m_output_video_stream->codecpar);
 m_output_video_codec_context->time_base = m_format_context->streams[m_video_stream_index]->time_base;
 
 //TODO(P1): Set these to match the input stream?
 m_output_video_codec_context->max_b_frames = 2;
 m_output_video_codec_context->gop_size = 12;
 m_output_video_codec_context->framerate = m_format_context->streams[m_video_stream_index]->r_frame_rate;
 //m_output_codec_context->refcounted_frames = 0;
 if (m_output_video_stream->codecpar->codec_id == AV_CODEC_ID_H264) {
 av_opt_set(m_output_video_codec_context, "preset", "ultrafast", 0);
 } else if (m_output_video_stream->codecpar->codec_id == AV_CODEC_ID_H265) {
 av_opt_set(m_output_video_codec_context, "preset", "ultrafast", 0);
 } else {
 av_opt_set_int(m_output_video_codec_context, "lossless", 1, 0);
 }
 avcodec_parameters_from_context(m_output_video_stream->codecpar, m_output_video_codec_context);

 m_output_audio_codec = avcodec_find_encoder(m_output_format->audio_codec);
 if (!m_output_audio_codec) {
 printf("Failed to create audio codec.\n");
 return false;
 }



I've commented out all of the audio stream init beyond this next line, because this is where
the trouble begins. Creating this output stream causes the null reference I mentioned. If I
uncomment everything below here, I still get the null deref. If I comment out this line, the
deref exception vanishes. (IOW, I commented out more and more code until I found that this
was the trigger that caused the problem.)


I assume that there's something I'm doing wrong in the rest of the commented out code, that,
when fixed, will fix the nullptr and give me a working audio stream.


m_output_audio_stream = avformat_new_stream(m_output_format_context, m_output_audio_codec);
 if (!m_output_audio_stream) {
 printf("Failed to find audio format.\n");
 return false;
 }
 /*
 m_output_audio_codec_context = avcodec_alloc_context3(m_output_audio_codec);
 if (!m_output_audio_codec_context) {
 printf("Failed to create audio codec context.\n");
 return(false);
 }
 m_output_audio_stream->codecpar->codec_id = m_output_format->audio_codec;
 m_output_audio_stream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
 m_output_audio_stream->codecpar->format = m_format_context->streams[m_audio_stream_index]->codecpar->format;
 m_output_audio_stream->codecpar->bit_rate = m_format_context->streams[m_audio_stream_index]->codecpar->bit_rate;
 m_output_audio_stream->avg_frame_rate = m_format_context->streams[m_audio_stream_index]->avg_frame_rate;
 avcodec_parameters_to_context(m_output_audio_codec_context, m_output_audio_stream->codecpar);
 m_output_audio_codec_context->time_base = m_format_context->streams[m_audio_stream_index]->time_base;
 */

 //TODO(P2): Free assets that have been allocated.
 err = avcodec_open2(m_output_video_codec_context, m_output_video_codec, nullptr);
 if (err < 0) {
 printf("Failed to open codec.\n");
 return false;
 }

 if (!(m_output_format->flags & AVFMT_NOFILE)) {
 err = avio_open(&m_output_format_context->pb, video_file_name.c_str(), AVIO_FLAG_WRITE);
 if (err < 0) {
 printf("Failed to open output file.");
 return false;
 }
 }

 err = avformat_write_header(m_output_format_context, NULL);
 if (err < 0) {
 printf("Failed to write header.\n");
 return false;
 }

 av_dump_format(m_output_format_context, 0, video_file_name.c_str(), 1);

 return true;
}


//TODO(P2): make this a member. (Thanks to https://emvlo.wordpress.com/2016/03/10/sws_scale/)
void PrepareFlipFrameJ420(AVFrame* pFrame) {
 for (int i = 0; i < 4; i++) {
 if (i)
 pFrame->data[i] += pFrame->linesize[i] * ((pFrame->height >> 1) - 1);
 else
 pFrame->data[i] += pFrame->linesize[i] * (pFrame->height - 1);
 pFrame->linesize[i] = -pFrame->linesize[i];
 }
}



This is where we take an altered frame and write it to the output container. This works fine
as long as we haven't set up an audio stream in the output container.


bool MediaContainerMgr::output_video_frame(uint8_t* buf) {
 int err;

 if (!m_output_video_frame) {
 m_output_video_frame = av_frame_alloc();
 m_output_video_frame->format = AV_PIX_FMT_YUV420P;
 m_output_video_frame->width = m_output_video_codec_context->width;
 m_output_video_frame->height = m_output_video_codec_context->height;
 err = av_frame_get_buffer(m_output_video_frame, 32);
 if (err < 0) {
 printf("Failed to allocate output frame.\n");
 return false;
 }
 }

 if (!m_output_scale_context) {
 m_output_scale_context = sws_getContext(m_output_video_codec_context->width, m_output_video_codec_context->height, 
 AV_PIX_FMT_RGB24,
 m_output_video_codec_context->width, m_output_video_codec_context->height, 
 AV_PIX_FMT_YUV420P, SWS_BICUBIC, nullptr, nullptr, nullptr);
 }

 int inLinesize[1] = { 3 * m_output_video_codec_context->width };
 sws_scale(m_output_scale_context, (const uint8_t* const*)&buf, inLinesize, 0, m_output_video_codec_context->height,
 m_output_video_frame->data, m_output_video_frame->linesize);
 PrepareFlipFrameJ420(m_output_video_frame);
 //TODO(P0): Switch m_frame to be m_input_video_frame so I don't end up using the presentation timestamp from
 // an audio frame if I threadify the frame reading.
 m_output_video_frame->pts = m_frame->pts;
 printf("Output PTS: %d, time_base: %d/%d\n", m_output_video_frame->pts,
 m_output_video_codec_context->time_base.num, m_output_video_codec_context->time_base.den);
 err = avcodec_send_frame(m_output_video_codec_context, m_output_video_frame);
 if (err < 0) {
 printf(" ERROR sending new video frame output: ");
 switch (err) {
 case AVERROR(EAGAIN):
 printf("AVERROR(EAGAIN): %d\n", err);
 break;
 case AVERROR_EOF:
 printf("AVERROR_EOF: %d\n", err);
 break;
 case AVERROR(EINVAL):
 printf("AVERROR(EINVAL): %d\n", err);
 break;
 case AVERROR(ENOMEM):
 printf("AVERROR(ENOMEM): %d\n", err);
 break;
 }

 return false;
 }

 AVPacket pkt;
 av_init_packet(&pkt);
 pkt.data = nullptr;
 pkt.size = 0;
 pkt.flags |= AV_PKT_FLAG_KEY;
 int ret = 0;
 if ((ret = avcodec_receive_packet(m_output_video_codec_context, &pkt)) == 0) {
 static int counter = 0;
 printf("pkt.key: 0x%08x, pkt.size: %d, counter:\n", pkt.flags & AV_PKT_FLAG_KEY, pkt.size, counter++);
 uint8_t* size = ((uint8_t*)pkt.data);
 printf("sizes: %d %d %d %d %d %d %d %d %d\n", size[0], size[1], size[2], size[2], size[3], size[4], size[5], size[6], size[7]);
 av_interleaved_write_frame(m_output_format_context, &pkt);
 }
 printf("push: %d\n", ret);
 av_packet_unref(&pkt);

 return true;
}

bool MediaContainerMgr::finalize_output() {
 if (!m_recording)
 return true;

 AVPacket pkt;
 av_init_packet(&pkt);
 pkt.data = nullptr;
 pkt.size = 0;

 for (;;) {
 avcodec_send_frame(m_output_video_codec_context, nullptr);
 if (avcodec_receive_packet(m_output_video_codec_context, &pkt) == 0) {
 av_interleaved_write_frame(m_output_format_context, &pkt);
 printf("final push:\n");
 } else {
 break;
 }
 }

 av_packet_unref(&pkt);

 av_write_trailer(m_output_format_context);
 if (!(m_output_format->flags & AVFMT_NOFILE)) {
 int err = avio_close(m_output_format_context->pb);
 if (err < 0) {
 printf("Failed to close file. err: %d\n", err);
 return false;
 }
 }

 return true;
}



EDIT
The call stack on the crash (which I should have included in the original question) :


avformat-58.dll!compute_muxer_pkt_fields(AVFormatContext * s, AVStream * st, AVPacket * pkt) Line 630 C
avformat-58.dll!write_packet_common(AVFormatContext * s, AVStream * st, AVPacket * pkt, int interleaved) Line 1122 C
avformat-58.dll!write_packets_common(AVFormatContext * s, AVPacket * pkt, int interleaved) Line 1186 C
avformat-58.dll!av_interleaved_write_frame(AVFormatContext * s, AVPacket * pkt) Line 1241 C
CamBot.exe!MediaContainerMgr::output_video_frame(unsigned char * buf) Line 553 C++
CamBot.exe!main() Line 240 C++



If I move the call to avformat_write_header so it's immediately before the audio stream initialization, I still get a crash, but in a different place. The crash happens on line 6459 of movenc.c, where we have :


/* Non-seekable output is ok if using fragmentation. If ism_lookahead
 * is enabled, we don't support non-seekable output at all. */
if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && // CRASH IS HERE
 (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead)) {
 av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
 return AVERROR(EINVAL);
}



The exception is a nullptr exception, where s->pb is NULL. The call stack is :


avformat-58.dll!mov_init(AVFormatContext * s) Line 6459 C
avformat-58.dll!init_muxer(AVFormatContext * s, AVDictionary * * options) Line 407 C
[Inline Frame] avformat-58.dll!avformat_init_output(AVFormatContext *) Line 489 C
avformat-58.dll!avformat_write_header(AVFormatContext * s, AVDictionary * * options) Line 512 C
CamBot.exe!MediaContainerMgr::init_video_output(const std::string & video_file_name, unsigned int width, unsigned int height) Line 424 C++
CamBot.exe!main() Line 183 C++



-
What’s new in Piwik 2.16.0 ?
In this blog post we showcase what is new in Piwik 2.16.0 and why you should upgrade your Piwik to this latest release !
Piwik 2.16.0 is currently in Release Candidate and you can already use it by following these simple instructions. Piwik 2.16.0 will be officially released in a few days.
To see the list of all 250+ changes, read the Piwik 2.16.0 changelog.
Long Term Support for Piwik 2.X
Piwik 2.16.0 is our Long Term Support version for Piwik 2. Learn more about Piwik LTS.
New : Custom Dimensions feature
With Custom Dimensions you can assign any custom data to your visitors or actions (like pages, events, …) and then visualize the reports of how many visits, conversions, pageviews, etc. there were for each Custom Dimension. They are similar to Custom Variables see the comparison of Custom Dimensions and Custom Variables.
The new Custom Dimensions plugin is available on the Piwik Marketplace.
Learn more about creating, tracking, reporting, managing, segmenting custom dimensions in the Custom Dimensions user guide.
View the list of all visitors who reached a specific goal
All Goal reports now include a link below the Goal report summary, that lets you see in one click all users that have converted any of your Goals :
Events reports : option to view all columns : min, max and avg values
By default in Actions > Events report, the columns displayed are “Total events” (Total number of events) and “Total value” (the sum of event values). It is now possible to click on the footer icon
to view more detailed columns about event values : minimum event value, maximum event value, and average event value.
Allow zoom to country in realtime visitor map
In the real time map in Piwik (which displays your users activity appearing in real time !), it is now possible to zoom on a given country :
Export all Records : new ‘all’ option in the Row limit selector
It is now possible to export all of the data in your reports directly from the user interface ! Select ‘all’ in the row limit selector before exporting your data reports :
New themes on the Marketplace !
Feel like a change of colors ? Try out the new community submitted Piwik Themes on the Marketplace ! Learn how to install a new theme in Piwik (in only a few clicks).
Let Super User view and edit segments created by other users
As a Super User of Piwik, it can be very useful to view all Custom Segments created by all users. Starting in Piwik 2.16.0 any Super User can now view all Segments for a given website in the Segment selector :
- Segments that are shared with All users will now appear below a section “Shared with you :” (a segment can be shared to all users by any admin user by selecting “This segment is visible to All Users” in the Segment editor)
- Segments that are not shared with anyone are now also visible under the section “Visible to you because you have Super User access :”
New segment ‘deviceBrand’ to segment by Device Brand
You can now segment by device brands such as Apple, Samsung, LG, Google, Nokia, Sony, Lenovo, Alcatel, etc. The complete list of device brands you can use is listed on the Segmentation developer guide.
New segment ‘actionType’ to view only particular Actions types (pagesviews, downloads, outlinks, events…)
Use the new “Action type” segment to view only particular actions such as : pageviews, contents, sitesearches, events, outlinks and downloads.
New segment : ‘actionUrl’ to view any actions that matches a given URL
Use the new “Action URL” segment to view any action that matches a given URL, whether they are Pageviews, Site searches, Contents, Downloads or Events.
New segment operators : “Starts with” and “Ends with”
The new segment operators “Starts with” and “Ends with” can come handy when creating Custom Segments, and complement well the existing segment operators : Contains, Does not contain, Equals, Not equals, Greater than or equal to, Less than or equal to.
Learn more about Segmentation in our user guides or in the Segmentation developer guide.
Making Piwik more accessible
Web accessibility refers to the inclusive practice of removing barriers that prevent interaction with, or access to applications or websites, by people with disabilities. When sites are correctly designed, developed and edited, all users have equal access to information and functionality.
In Piwik 2.16.0, and with the help of high school students from the Catalyst Academy, we have made several improvements that make Piwik more accessible :
- Menu now include the ARIA metadata (to make menus easier to navigate and use)
- Page titles and various key tooltips have been improved (to give a better context to the data)
- Keyboard access has been much improvement and Piwik is starting to be usable with the keyboard ! (this is very useful as many users are not able to use a mouse, and they should be able to view Piwik reports with the keyboard only)
- ‘Skip to main content’ link (when pressing the TAB key) now skips the cursor to the page content.
- Search bar was further improved : try it by pressing the ‘f’ key (useful to open any Piwik report or page without using the mouse)
New user preference : display times either as 24h format or AM/PM format
Users can now select whether times should be displayed in 24h format (16:20) or in AM/PM format (4:20pm)
Other admins and Super Users are not visible to users with ‘admin’ permissions anymore
Piwik 2.16.0 just became even more respectful of your privacy : any user you created and assigned an “admin” permission will not be able to view all other usernames anymore. This change was requested by many Piwik users who rightfully preferred not to disclose all usernames to any ‘admin’ user.
As a result of this change, when a user with ‘admin’ permission (admin user) wants to give additional permission to another user (target user), the admin user will now need to know the target username and enter it in the Manage Users interface :
New Config file viewer
A new menu entry Administration > Diagnostics > Config file, lets Super Users view all config values in the UI :
This new screen serves several purposes :
- help Piwik administrators discover and learn about all the possible config file settings that Piwik offers.
- let Super Users and Admins easily view any overridden config.ini.php INI setting without having to open the config file on the server.
New report ‘Personal settings > Custom Variables’ displays custom variable usage
A new report visible to Super Users lets you see how your Custom Variables slots are being used, which ones are still unused, and how many times a given custom variable name was used.
Learn more about Custom Variables.
Improvements to Heartbeat feature to accurately count time spent on the last page
The heartbeat feature which lets you accurately track how long do visitors spend on your website, has been improved in 2.16.0. If you would like to measure how long do people spend on your pages (even if they don’t interact with your website or app), then consider using the heartbeat feature. Learn more in our guide Accurately measure the time spent on each page.
New AnonymousPiwikUsageMeasurement plugin
AnonymousPiwikUsageMeasurement plugin was created for those who would like to measure how their Piwik services is being used. This plugin also sends anonymised tracking data to our demo-anonymous.piwik.org which will help us learn how your Piwik is used and how we could improve the application. Learn more about AnonymousPiwikUsageMeasurement plugin.
Show a warning when Piwik is used as a SuperUser via HTTP
It is highly recommended to use HTTPS (SSL) for your Piwik server. If you are logged in as a Super User and viewing any Administration pages, you will now see a warning notification message at the top of the screen inviting you to use HTTPS :
MySQL 5.7+ support
The awesome Piwik community has helped us identify several issues with MySQL 5.7 support and Piwik is now fully compatible with the latest MySQL version 5.7+. Piwik is officially compatible with MySQL >= 4.1 and up to Mysql 5.7 ! Piwik is also compatible with MariaDB.
Better detection of new devices and robots
Our Device Detector library can now detect many new types of devices : smart TVs, new tablets and mobile phones, and more. New bots were added to our list of bots to keep your analytics report meaningful.
Learn more : What Device Detector is able to detect, About Device Detector.
New Referrer Spammers
Every week we keep updating our community-list of referrer spammers. More than 50 new spammers were added since the last Piwik release !
Note that the list of referrer spammer is automatically updated every week in your Piwik, so you need to wait at most one week to benefit from the very latest list.
Learn more about Stopping Referrer Spam in Analytics reports.
Ability to support new SMS providers to send Scheduled Reports by text message
When you create scheduled reports in Piwik, you can specify one or several email addresses (to send reports by email) and you can also configure phone numbers (so your reports are sent to your phone via text message). So far we only support one SMS Provider “Clockwork SMS” but it is now possible for anyone to create a very simple plugin that adds a new SMS Provider to Piwik.
A new SMS Provider plugin was released on the Marketplace : FreeMobileMessaging. If you have a favorite SMS Provider, we encourage you to create a new plugin for it !
Piwik Consulting mentions
A few new mentions of Piwik Consultants were added into Piwik to let users know that they can get Professional Help, and additional services and products. For example a new widget was added to the default dashboard. If you provide your Piwik service to your own clients, maybe you would like to remove the Professional services widget and other ads, see this FAQ : How do I remove from Piwik the links to “Piwik Consultants” or to “Professional Services” ?
Stability, Reliability and Performance
Dozens of other bugs were fixed (including several Major bugs) and many small improvements are included in this release. All these changes make Piwik more stable and reliable, as well as easier to troubleshoot and maintain. We are proud to be able to offer Piwik 2.16.0 as our Long Term Support release !
If you have any feedback, questions, suggestion, or bug to report, please join our Piwik Community Forums.
We hope you will love this 2.16.0 release as much as we loved making it.
Happy Analytics !
-
What’s new in Piwik 2.16.0 ?
In this blog post we showcase what is new in Piwik 2.16.0 and why you should upgrade your Piwik to this latest release !
Piwik 2.16.0 is currently in Release Candidate and you can already use it by following these simple instructions. Piwik 2.16.0 will be officially released in a few days.
To see the list of all 250+ changes, read the Piwik 2.16.0 changelog.
Long Term Support for Piwik 2.X
Piwik 2.16.0 is our Long Term Support version for Piwik 2. Learn more about Piwik LTS.
New : Custom Dimensions feature
With Custom Dimensions you can assign any custom data to your visitors or actions (like pages, events, …) and then visualize the reports of how many visits, conversions, pageviews, etc. there were for each Custom Dimension. They are similar to Custom Variables see the comparison of Custom Dimensions and Custom Variables.
The new Custom Dimensions plugin is available on the Piwik Marketplace.
Learn more about creating, tracking, reporting, managing, segmenting custom dimensions in the Custom Dimensions user guide.
View the list of all visitors who reached a specific goal
All Goal reports now include a link below the Goal report summary, that lets you see in one click all users that have converted any of your Goals :
Events reports : option to view all columns : min, max and avg values
By default in Actions > Events report, the columns displayed are “Total events” (Total number of events) and “Total value” (the sum of event values). It is now possible to click on the footer icon
to view more detailed columns about event values : minimum event value, maximum event value, and average event value.
Allow zoom to country in realtime visitor map
In the real time map in Piwik (which displays your users activity appearing in real time !), it is now possible to zoom on a given country :
Export all Records : new ‘all’ option in the Row limit selector
It is now possible to export all of the data in your reports directly from the user interface ! Select ‘all’ in the row limit selector before exporting your data reports :
New themes on the Marketplace !
Feel like a change of colors ? Try out the new community submitted Piwik Themes on the Marketplace ! Learn how to install a new theme in Piwik (in only a few clicks).
Let Super User view and edit segments created by other users
As a Super User of Piwik, it can be very useful to view all Custom Segments created by all users. Starting in Piwik 2.16.0 any Super User can now view all Segments for a given website in the Segment selector :
- Segments that are shared with All users will now appear below a section “Shared with you :” (a segment can be shared to all users by any admin user by selecting “This segment is visible to All Users” in the Segment editor)
- Segments that are not shared with anyone are now also visible under the section “Visible to you because you have Super User access :”
New segment ‘deviceBrand’ to segment by Device Brand
You can now segment by device brands such as Apple, Samsung, LG, Google, Nokia, Sony, Lenovo, Alcatel, etc. The complete list of device brands you can use is listed on the Segmentation developer guide.
New segment ‘actionType’ to view only particular Actions types (pagesviews, downloads, outlinks, events…)
Use the new “Action type” segment to view only particular actions such as : pageviews, contents, sitesearches, events, outlinks and downloads.
New segment : ‘actionUrl’ to view any actions that matches a given URL
Use the new “Action URL” segment to view any action that matches a given URL, whether they are Pageviews, Site searches, Contents, Downloads or Events.
New segment operators : “Starts with” and “Ends with”
The new segment operators “Starts with” and “Ends with” can come handy when creating Custom Segments, and complement well the existing segment operators : Contains, Does not contain, Equals, Not equals, Greater than or equal to, Less than or equal to.
Learn more about Segmentation in our user guides or in the Segmentation developer guide.
Making Piwik more accessible
Web accessibility refers to the inclusive practice of removing barriers that prevent interaction with, or access to applications or websites, by people with disabilities. When sites are correctly designed, developed and edited, all users have equal access to information and functionality.
In Piwik 2.16.0, and with the help of high school students from the Catalyst Academy, we have made several improvements that make Piwik more accessible :
- Menu now include the ARIA metadata (to make menus easier to navigate and use)
- Page titles and various key tooltips have been improved (to give a better context to the data)
- Keyboard access has been much improvement and Piwik is starting to be usable with the keyboard ! (this is very useful as many users are not able to use a mouse, and they should be able to view Piwik reports with the keyboard only)
- ‘Skip to main content’ link (when pressing the TAB key) now skips the cursor to the page content.
- Search bar was further improved : try it by pressing the ‘f’ key (useful to open any Piwik report or page without using the mouse)
New user preference : display times either as 24h format or AM/PM format
Users can now select whether times should be displayed in 24h format (16:20) or in AM/PM format (4:20pm)
Other admins and Super Users are not visible to users with ‘admin’ permissions anymore
Piwik 2.16.0 just became even more respectful of your privacy : any user you created and assigned an “admin” permission will not be able to view all other usernames anymore. This change was requested by many Piwik users who rightfully preferred not to disclose all usernames to any ‘admin’ user.
As a result of this change, when a user with ‘admin’ permission (admin user) wants to give additional permission to another user (target user), the admin user will now need to know the target username and enter it in the Manage Users interface :
New Config file viewer
A new menu entry Administration > Diagnostics > Config file, lets Super Users view all config values in the UI :
This new screen serves several purposes :
- help Piwik administrators discover and learn about all the possible config file settings that Piwik offers.
- let Super Users and Admins easily view any overridden config.ini.php INI setting without having to open the config file on the server.
New report ‘Personal settings > Custom Variables’ displays custom variable usage
A new report visible to Super Users lets you see how your Custom Variables slots are being used, which ones are still unused, and how many times a given custom variable name was used.
Learn more about Custom Variables.
Improvements to Heartbeat feature to accurately count time spent on the last page
The heartbeat feature which lets you accurately track how long do visitors spend on your website, has been improved in 2.16.0. If you would like to measure how long do people spend on your pages (even if they don’t interact with your website or app), then consider using the heartbeat feature. Learn more in our guide Accurately measure the time spent on each page.
New AnonymousPiwikUsageMeasurement plugin
AnonymousPiwikUsageMeasurement plugin was created for those who would like to measure how their Piwik services is being used. This plugin also sends anonymised tracking data to our demo-anonymous.piwik.org which will help us learn how your Piwik is used and how we could improve the application. Learn more about AnonymousPiwikUsageMeasurement plugin.
Show a warning when Piwik is used as a SuperUser via HTTP
It is highly recommended to use HTTPS (SSL) for your Piwik server. If you are logged in as a Super User and viewing any Administration pages, you will now see a warning notification message at the top of the screen inviting you to use HTTPS :
MySQL 5.7+ support
The awesome Piwik community has helped us identify several issues with MySQL 5.7 support and Piwik is now fully compatible with the latest MySQL version 5.7+. Piwik is officially compatible with MySQL >= 4.1 and up to Mysql 5.7 ! Piwik is also compatible with MariaDB.
Better detection of new devices and robots
Our Device Detector library can now detect many new types of devices : smart TVs, new tablets and mobile phones, and more. New bots were added to our list of bots to keep your analytics report meaningful.
Learn more : What Device Detector is able to detect, About Device Detector.
New Referrer Spammers
Every week we keep updating our community-list of referrer spammers. More than 50 new spammers were added since the last Piwik release !
Note that the list of referrer spammer is automatically updated every week in your Piwik, so you need to wait at most one week to benefit from the very latest list.
Learn more about Stopping Referrer Spam in Analytics reports.
Ability to support new SMS providers to send Scheduled Reports by text message
When you create scheduled reports in Piwik, you can specify one or several email addresses (to send reports by email) and you can also configure phone numbers (so your reports are sent to your phone via text message). So far we only support one SMS Provider “Clockwork SMS” but it is now possible for anyone to create a very simple plugin that adds a new SMS Provider to Piwik.
A new SMS Provider plugin was released on the Marketplace : FreeMobileMessaging. If you have a favorite SMS Provider, we encourage you to create a new plugin for it !
Piwik PRO mentions
A few new mentions of Piwik PRO were added into Piwik to let users know that they can get Professional Help, and additional services and products. For example a new widget was added to the default dashboard. If you provide your Piwik service to your own clients, maybe you would like to remove the Piwik PRO widget and other ads, see this FAQ : How do I remove from Piwik the links to “Piwik PRO” or to “Professional Services” ?
Stability, Reliability and Performance
Dozens of other bugs were fixed (including several Major bugs) and many small improvements are included in this release. All these changes make Piwik more stable and reliable, as well as easier to troubleshoot and maintain. We are proud to be able to offer Piwik 2.16.0 as our Long Term Support release !
If you have any feedback, questions, suggestion, or bug to report, please join our Piwik Community Forums.
We hope you will love this 2.16.0 release as much as we loved making it.
Happy Analytics !