Recherche avancée

Médias (1)

Mot : - Tags -/MediaSPIP 0.2

Autres articles (111)

  • 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 (...)

  • Supporting all media types

    13 avril 2011, par

    Unlike most software and media-sharing platforms, MediaSPIP aims to manage as many different media types as possible. The following are just a few examples from an ever-expanding list of supported formats : images : png, gif, jpg, bmp and more audio : MP3, Ogg, Wav and more video : AVI, MP4, OGV, mpg, mov, wmv and more text, code and other data : OpenOffice, Microsoft Office (Word, PowerPoint, Excel), web (html, CSS), LaTeX, Google Earth and (...)

  • Les notifications de la ferme

    1er décembre 2010, par

    Afin d’assurer une gestion correcte de la ferme, il est nécessaire de notifier plusieurs choses lors d’actions spécifiques à la fois à l’utilisateur mais également à l’ensemble des administrateurs de la ferme.
    Les notifications de changement de statut
    Lors d’un changement de statut d’une instance, l’ensemble des administrateurs de la ferme doivent être notifiés de cette modification ainsi que l’utilisateur administrateur de l’instance.
    À la demande d’un canal
    Passage au statut "publie"
    Passage au (...)

Sur d’autres sites (6567)

  • ffmpeg produces duplicate pts with "wallclock_as_timestamps 1" option on MKV

    15 avril 2024, par Jax2171

    I need to get real time reference of every keyframe captured by an IP camera. The -wallclock_as_timestamps 1 option seems to do the trick for us, however we are forced to replace the TS output container with MKV to get a correct PTS epoch value 1712996356.833000.

    


    Here is the ffmpeg command used :

    


    ffmpeg -report -use_wallclock_as_timestamps 1 -rtsp_transport tcp -i rtsp://user:password1@192.168.5.21/cam/realmonitor?channel=1channel1[1]=1subtype=0 -c:v copy -c:a aac -copyts -f matroska -y rec.mkv


    


    The capture process runs without any relevant worning or error messages.

    


    However, playing the captured video with any player shows very short and evident but very annoying lags. Upon investigation I discovered that many frame PTSs have the same value. The command I used to show duplicate PTSs is as follows :

    


    ffprobe -v error -show_entries frame=pkt_pts_time -select_streams v -of csv=p=0 rec.mkv | sort | uniq -d


    


    On a recording of about 10 minutes the result of the duplicate PTS is the following :

    


    1713086493.367000
1713086493.368000
1713086493.370000
1713086493.372000
1713086543.714000
1713086558.793000
1713086558.817000
1713086558.872000
1713086561.780000
1713086564.642000
1713086564.657000
1713086564.778000
1713086565.794000
...


    


    I'm not sure if the lag problem is caused by this, however the problem does not occur with the TS container, which however I cannot use due to the PTS values being roundly 33 bit.

    


    The -vsync 0 or -vsync 2 options on input or output didn't help.

    


    This is the log using the -report option :

    


        ffmpeg started on 2024-04-15 at 09:04:38
Report written to "ffmpeg-20240415-090438.log"
Log level: 48
Command line:
ffmpeg -report -stats -hide_banner -use_wallclock_as_timestamps 1 -rtsp_transport tcp -i "rtsp://user:password1@192.168.5.21/cam/realmonitor?channel=1channel1[1]=1subtype=0" -c:v copy -c:a aac -copyts -f matroska -y rec.mkv
Splitting the commandline.
Reading option '-report' ... matched as option 'report' (generate a report) with argument '1'.
Reading option '-stats' ... matched as option 'stats' (print progress report during encoding) with argument '1'.
Reading option '-hide_banner' ... matched as option 'hide_banner' (do not show program banner) with argument '1'.
Reading option '-use_wallclock_as_timestamps' ... matched as AVOption 'use_wallclock_as_timestamps' with argument '1'.
Reading option '-rtsp_transport' ... matched as AVOption 'rtsp_transport' with argument 'tcp'.
Reading option '-i' ... matched as input url with argument 'rtsp://user:password1@192.168.5.21/cam/realmonitor?channel=1channel1[1]=1subtype=0'.
Reading option '-c:v' ... matched as option 'c' (codec name) with argument 'copy'.
Reading option '-c:a' ... matched as option 'c' (codec name) with argument 'aac'.
Reading option '-copyts' ... matched as option 'copyts' (copy timestamps) with argument '1'.
Reading option '-f' ... matched as option 'f' (force format) with argument 'matroska'.
Reading option '-y' ... matched as option 'y' (overwrite output files) with argument '1'.
Reading option 'rec.mkv' ... matched as output url.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option report (generate a report) with argument 1.
Applying option stats (print progress report during encoding) with argument 1.
Applying option hide_banner (do not show program banner) with argument 1.
Applying option copyts (copy timestamps) with argument 1.
Applying option y (overwrite output files) with argument 1.
Successfully parsed a group of options.
Parsing a group of options: input url rtsp://user:password1@192.168.5.21/cam/realmonitor?channel=1channel1[1]=1subtype=0.
Successfully parsed a group of options.
Opening an input file: rtsp://user:password1@192.168.5.21/cam/realmonitor?channel=1channel1[1]=1subtype=0.
[tcp @ 0x1646660] No default whitelist set
[tcp @ 0x1646660] Original list of addresses:
[tcp @ 0x1646660] Address 192.168.5.21 port 554
[tcp @ 0x1646660] Interleaved list of addresses:
[tcp @ 0x1646660] Address 192.168.5.21 port 554
[tcp @ 0x1646660] Starting connection attempt to 192.168.5.21 port 554
[tcp @ 0x1646660] Successfully connected to 192.168.5.21 port 554
[rtsp @ 0x1645e70] SDP:
v=0
o=- 2251950012 2251950012 IN IP4 0.0.0.0
s=Media Server
c=IN IP4 0.0.0.0
t=0 0
a=control:*
a=packetization-supported:DH
a=rtppayload-supported:DH
a=range:npt=now-
a=x-packetization-supported:IV
a=x-rtppayload-supported:IV
m=video 0 RTP/AVP 96
a=control:trackID=0
a=framerate:25.000000
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=4D4028;sprop-parameter-sets=Z01AKKaAeAIn5ZuAgICgAAADACAAAAZQgAA=,aO48gAA=
a=recvonly
m=audio 0 RTP/AVP 97
a=control:trackID=1
a=rtpmap:97 MPEG4-GENERIC/16000
a=fmtp:97 streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config=1408
a=recvonly

[rtsp @ 0x1645e70] video codec set to: h264
[rtsp @ 0x1645e70] RTP Packetization Mode: 1
[rtsp @ 0x1645e70] RTP Profile IDC: 4d Profile IOP: 40 Level: 28
[rtsp @ 0x1645e70] Extradata set to 0x164af98 (size: 39)
[rtsp @ 0x1645e70] audio codec set to: aac
[rtsp @ 0x1645e70] audio samplerate set to: 16000
[rtsp @ 0x1645e70] audio channels set to: 1
[rtsp @ 0x1645e70] setting jitter buffer size to 0
[rtsp @ 0x1645e70] setting jitter buffer size to 0
[rtsp @ 0x1645e70] hello state=0
Failed to parse interval end specification ''
[h264 @ 0x164ab30] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x164ab30] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x164ab30] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x164ab30] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x164ab30] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x164ab30] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x164ab30] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x164ab30] Format yuvj420p chosen by get_format().
[h264 @ 0x164ab30] Reinit context to 1920x1088, pix_fmt: yuvj420p
[h264 @ 0x164ab30] nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 3
[h264 @ 0x164ab30] nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 3
[h264 @ 0x164ab30] nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 3
[h264 @ 0x164ab30] nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 3
[h264 @ 0x164ab30] nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 3
[h264 @ 0x164ab30] nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 3
[rtsp @ 0x1645e70] All info found
Input #0, rtsp, from 'rtsp://user:password1@192.168.5.21/cam/realmonitor?channel=1channel1[1]=1subtype=0':
  Metadata:
    title           : Media Server
  Duration: N/A, start: 1713164678.794625, bitrate: N/A
    Stream #0:0, 22, 1/90000: Video: h264 (Main), yuvj420p(pc, bt709, progressive), 1920x1080, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1, 15, 1/16000: Audio: aac (LC), 16000 Hz, mono, fltp
Successfully opened the file.
Parsing a group of options: output url rec.mkv.
Applying option c:v (codec name) with argument copy.
Applying option c:a (codec name) with argument aac.
Applying option f (force format) with argument matroska.
Successfully parsed a group of options.
Opening an output file: rec.mkv.
[file @ 0x1699f30] Setting default whitelist 'file,crypto,data'
Successfully opened the file.
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
Press [q] to stop, [?] for help
cur_dts is invalid st:0 (0) [init:1 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
cur_dts is invalid st:1 (0) [init:0 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
detected 4 logical cores
[graph_0_in_0_1 @ 0x1682bb0] Setting 'time_base' to value '1/16000'
[graph_0_in_0_1 @ 0x1682bb0] Setting 'sample_rate' to value '16000'
[graph_0_in_0_1 @ 0x1682bb0] Setting 'sample_fmt' to value 'fltp'
[graph_0_in_0_1 @ 0x1682bb0] Setting 'channel_layout' to value '0x4'
[graph_0_in_0_1 @ 0x1682bb0] tb:1/16000 samplefmt:fltp samplerate:16000 chlayout:0x4
[format_out_0_1 @ 0x187f2e0] Setting 'sample_fmts' to value 'fltp'
[format_out_0_1 @ 0x187f2e0] Setting 'sample_rates' to value '96000|88200|64000|48000|44100|32000|24000|22050|16000|12000|11025|8000|7350'
[AVFilterGraph @ 0x164fd70] query_formats: 4 queried, 9 merged, 0 already done, 0 delayed
[matroska @ 0x169c330] get_metadata_duration returned: 0
Output #0, matroska, to 'rec.mkv':
  Metadata:
    title           : Media Server
    encoder         : Lavf58.45.100
    Stream #0:0, 0, 1/1000: Video: h264 (Main) (H264 / 0x34363248), yuvj420p(pc, bt709, progressive), 1920x1080, q=2-31, 25 fps, 25 tbr, 1k tbn, 90k tbc
    Stream #0:1, 0, 1/1000: Audio: aac (LC) ([255][0][0][0] / 0x00FF), 16000 Hz, mono, fltp, 69 kb/s
    Metadata:
      encoder         : Lavc58.91.100 aac
cur_dts is invalid st:0 (0) [init:1 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
cur_dts is invalid st:1 (0) [init:1 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
cur_dts is invalid st:0 (0) [init:1 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
[matroska @ 0x169c330] Starting new cluster with timestamp 1713164678731 at offset 770 bytes
[matroska @ 0x169c330] Writing block of size 581 with pts 1713164678731, dts 1713164678731, duration 64 at relative offset 14 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 517 with pts 1713164678795, dts 1713164678795, duration 64 at relative offset 602 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 376900 with pts 1713164678872, dts 1713164678872, duration 40 at relative offset 1126 in cluster at offset 770. TrackNumber 1, keyframe 1
[matroska @ 0x169c330] Writing block of size 8172 with pts 1713164678912, dts 1713164678912, duration 40 at relative offset 378034 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 672 with pts 1713164678912, dts 1713164678912, duration 64 at relative offset 386213 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 550 with pts 1713164679177, dts 1713164679177, duration 64 at relative offset 386892 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 7654 with pts 1713164679178, dts 1713164679178, duration 40 at relative offset 387449 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 7483 with pts 1713164679213, dts 1713164679213, duration 40 at relative offset 395110 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 7703 with pts 1713164679242, dts 1713164679242, duration 40 at relative offset 402600 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 565 with pts 1713164679242, dts 1713164679242, duration 64 at relative offset 410310 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 7650 with pts 1713164679271, dts 1713164679271, duration 40 at relative offset 410882 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 585 with pts 1713164679271, dts 1713164679271, duration 64 at relative offset 418539 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 8682 with pts 1713164679301, dts 1713164679301, duration 40 at relative offset 419131 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 8888 with pts 1713164679330, dts 1713164679330, duration 40 at relative offset 427820 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 506 with pts 1713164679330, dts 1713164679330, duration 64 at relative offset 436715 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 8019 with pts 1713164679360, dts 1713164679360, duration 40 at relative offset 437228 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 7919 with pts 1713164679361, dts 1713164679361, duration 40 at relative offset 445254 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 7822 with pts 1713164679361, dts 1713164679361, duration 40 at relative offset 453180 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 699 with pts 1713164679361, dts 1713164679361, duration 64 at relative offset 461009 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 619 with pts 1713164679361, dts 1713164679361, duration 64 at relative offset 461715 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 7768 with pts 1713164679362, dts 1713164679362, duration 40 at relative offset 462341 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 8469 with pts 1713164679362, dts 1713164679362, duration 40 at relative offset 470116 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 601 with pts 1713164679362, dts 1713164679362, duration 64 at relative offset 478592 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 559 with pts 1713164679363, dts 1713164679363, duration 64 at relative offset 479200 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 8265 with pts 1713164679366, dts 1713164679366, duration 40 at relative offset 479766 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 7766 with pts 1713164679406, dts 1713164679406, duration 40 at relative offset 488038 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 531 with pts 1713164679415, dts 1713164679415, duration 64 at relative offset 495811 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 7753 with pts 1713164679446, dts 1713164679446, duration 40 at relative offset 496349 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 8274 with pts 1713164679486, dts 1713164679486, duration 40 at relative offset 504109 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 569 with pts 1713164679496, dts 1713164679496, duration 64 at relative offset 512390 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 8445 with pts 1713164679526, dts 1713164679526, duration 40 at relative offset 512966 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 522 with pts 1713164679535, dts 1713164679535, duration 64 at relative offset 521418 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 7922 with pts 1713164679566, dts 1713164679566, duration 40 at relative offset 521947 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 7954 with pts 1713164679606, dts 1713164679606, duration 40 at relative offset 529876 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 503 with pts 1713164679615, dts 1713164679615, duration 64 at relative offset 537837 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 11167 with pts 1713164679646, dts 1713164679646, duration 40 at relative offset 538347 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 503 with pts 1713164679655, dts 1713164679655, duration 64 at relative offset 549521 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 10534 with pts 1713164679686, dts 1713164679686, duration 40 at relative offset 550031 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 7607 with pts 1713164679726, dts 1713164679726, duration 40 at relative offset 560572 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 478 with pts 1713164679772, dts 1713164679772, duration 64 at relative offset 568186 in cluster at offset 770. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 7842 with pts 1713164679774, dts 1713164679774, duration 40 at relative offset 568671 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 9862 with pts 1713164679806, dts 1713164679806, duration 40 at relative offset 576520 in cluster at offset 770. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Starting new cluster with timestamp 1713164679815 at offset 587166 bytes
[matroska @ 0x169c330] Writing block of size 449 with pts 1713164679815, dts 1713164679815, duration 64 at relative offset 14 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 379456 with pts 1713164679870, dts 1713164679870, duration 40 at relative offset 470 in cluster at offset 587166. TrackNumber 1, keyframe 1
[matroska @ 0x169c330] Writing block of size 415 with pts 1713164679903, dts 1713164679903, duration 64 at relative offset 379934 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 7008 with pts 1713164679905, dts 1713164679905, duration 40 at relative offset 380356 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 6917 with pts 1713164679925, dts 1713164679925, duration 40 at relative offset 387371 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 513 with pts 1713164679935, dts 1713164679935, duration 64 at relative offset 394295 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 7111 with pts 1713164679966, dts 1713164679966, duration 40 at relative offset 394815 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 753 with pts 1713164679975, dts 1713164679975, duration 64 at relative offset 401933 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 7091 with pts 1713164680006, dts 1713164680006, duration 40 at relative offset 402693 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 7045 with pts 1713164680045, dts 1713164680045, duration 40 at relative offset 409791 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 659 with pts 1713164680055, dts 1713164680055, duration 64 at relative offset 416843 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 6983 with pts 1713164680086, dts 1713164680086, duration 40 at relative offset 417509 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 6932 with pts 1713164680127, dts 1713164680127, duration 40 at relative offset 424499 in cluster at offset 587166. TrackNumber 1, keyframe 0
frame=   35 fps=0.0 q=-1.0 size=     512kB time=475879:04:40.20 bitrate=   0.0kbits/s speed=3.35e+09x    
[matroska @ 0x169c330] Writing block of size 691 with pts 1713164680135, dts 1713164680135, duration 64 at relative offset 431438 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 6990 with pts 1713164680166, dts 1713164680166, duration 40 at relative offset 432136 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 651 with pts 1713164680176, dts 1713164680176, duration 64 at relative offset 439133 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 7046 with pts 1713164680206, dts 1713164680206, duration 40 at relative offset 439791 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 7130 with pts 1713164680246, dts 1713164680246, duration 40 at relative offset 446844 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 601 with pts 1713164680255, dts 1713164680255, duration 64 at relative offset 453981 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 7205 with pts 1713164680286, dts 1713164680286, duration 40 at relative offset 454589 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 561 with pts 1713164680295, dts 1713164680295, duration 64 at relative offset 461801 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 6936 with pts 1713164680326, dts 1713164680326, duration 40 at relative offset 462369 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 6822 with pts 1713164680366, dts 1713164680366, duration 40 at relative offset 469312 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 621 with pts 1713164680375, dts 1713164680375, duration 64 at relative offset 476141 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 6845 with pts 1713164680405, dts 1713164680405, duration 40 at relative offset 476769 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 6848 with pts 1713164680445, dts 1713164680445, duration 40 at relative offset 483621 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 588 with pts 1713164680455, dts 1713164680455, duration 64 at relative offset 490476 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 6828 with pts 1713164680486, dts 1713164680486, duration 40 at relative offset 491071 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 546 with pts 1713164680495, dts 1713164680495, duration 64 at relative offset 497906 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 6845 with pts 1713164680526, dts 1713164680526, duration 40 at relative offset 498459 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 6924 with pts 1713164680566, dts 1713164680566, duration 40 at relative offset 505311 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 508 with pts 1713164680576, dts 1713164680576, duration 64 at relative offset 512242 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 6844 with pts 1713164680606, dts 1713164680606, duration 40 at relative offset 512757 in cluster at offset 587166. TrackNumber 1, keyframe 0
frame=   48 fps= 47 q=-1.0 size=     512kB time=475879:04:40.72 bitrate=   0.0kbits/s speed=1.66e+09x    
[matroska @ 0x169c330] Writing block of size 587 with pts 1713164680615, dts 1713164680615, duration 64 at relative offset 519608 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 6859 with pts 1713164680645, dts 1713164680645, duration 40 at relative offset 520202 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 6855 with pts 1713164680686, dts 1713164680686, duration 40 at relative offset 527068 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 573 with pts 1713164680695, dts 1713164680695, duration 64 at relative offset 533930 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 6881 with pts 1713164680726, dts 1713164680726, duration 40 at relative offset 534510 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 10773 with pts 1713164680766, dts 1713164680766, duration 40 at relative offset 541398 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 520 with pts 1713164680775, dts 1713164680775, duration 64 at relative offset 552178 in cluster at offset 587166. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 6923 with pts 1713164680805, dts 1713164680805, duration 40 at relative offset 552705 in cluster at offset 587166. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Starting new cluster with timestamp 1713164680815 at offset 1146808 bytes
[matroska @ 0x169c330] Writing block of size 580 with pts 1713164680815, dts 1713164680815, duration 64 at relative offset 14 in cluster at offset 1146808. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 380085 with pts 1713164680864, dts 1713164680864, duration 40 at relative offset 601 in cluster at offset 1146808. TrackNumber 1, keyframe 1
[matroska @ 0x169c330] Writing block of size 9916 with pts 1713164680896, dts 1713164680896, duration 40 at relative offset 380694 in cluster at offset 1146808. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 541 with pts 1713164680901, dts 1713164680901, duration 64 at relative offset 390617 in cluster at offset 1146808. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 5877 with pts 1713164680925, dts 1713164680925, duration 40 at relative offset 391165 in cluster at offset 1146808. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] Writing block of size 529 with pts 1713164680935, dts 1713164680935, duration 64 at relative offset 397049 in cluster at offset 1146808. TrackNumber 2, keyframe 1
[matroska @ 0x169c330] Writing block of size 6661 with pts 1713164680966, dts 1713164680966, duration 40 at relative offset 397585 in cluster at offset 1146808. TrackNumber 1, keyframe 0
[matroska @ 0x169c330] end duration = 1713164681006
[matroska @ 0x169c330] stream 0 end duration = 1713164681006
[matroska @ 0x169c330] stream 1 end duration = 1713164680999
frame=   54 fps= 42 q=-1.0 Lsize=    1515kB time=475879:04:40.99 bitrate=   0.0kbits/s speed=1.33e+09x    
video:1493kB audio:20kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.099897%
Input file #0 (rtsp://user:password1@192.168.5.21/cam/realmonitor?channel=1channel1[1]=1subtype=0):
  Input stream #0:0 (video): 54 packets read (1529156 bytes); 
  Input stream #0:1 (audio): 35 packets read (9268 bytes); 35 frames decoded (35840 samples); 
  Total: 89 packets (1538424 bytes) demuxed
Output file #0 (rec.mkv):
  Output stream #0:0 (video): 54 packets muxed (1529156 bytes); 
  Output stream #0:1 (audio): 35 frames encoded (35840 samples); 36 packets muxed (20446 bytes); 
  Total: 90 packets (1549602 bytes) muxed
35 frames successfully decoded, 0 decoding errors
[AVIOContext @ 0x1667620] Statistics: 2 seeks, 7 writeouts
[aac @ 0x1673880] Qavg: 142.738
Exiting normally, received signal 15.


    


    In this short 3 second capture the duplicate timestamps are 1713164679.361000 and 1713164679.362000.

    


    How can I solve this problem ? What different approach could I use to achieve this goal ?

    


    Thanks in advance.

    


  • Why Matomo is the top Google Analytics alternative

    17 juin, par Joe

    You probably made the switch to Google Analytics 4 (GA4) when Google stopped collecting Universal Analytics (UA) data in July 2023. Up to that point, UA had long been the default analytics platform, despite its many limitations. 

    This was mostly because everyone loved its free nature and simple setup. A Google account was all you needed — even a free legacy G-Suite account worked perfectly. Looking at the analytics for just about any website was easy.

    That all changed with GA4, which addressed many of UA’s shortcomings by introducing a completely new way to model website data. Unfortunately, this also meant you couldn’t transfer historical data from UA into GA4, leading to more criticism. 

    Then there’s the added cost. GA4 is still free, but its limited functionality encourages you to upgrade to the enterprise version, Google Analytics 360 (GA360). Sure, you get lots of great functionality, less data sampling, and longer data retention periods, but it comes at a hefty price — $50,000 per year, to be exact.

    There are other options, though, and Matomo Analytics is one of the best. It’s an open-source, privacy-centric platform that offers advanced features of GA360 and more. 

    In this article, we’ll compare GA4, GA360, and Matomo and give you what you need to make an informed decision.

    Google Analytics 4 in a nutshell

    Google Analytics 4 is a great tool to use to start learning about web analytics. But soon enough, you’ll likely find that GA4 doesn’t quite cover all of your needs. 

    For example, it can’t provide a detailed view of user experiences, and Google doesn’t offer dedicated support or onboarding. There are other shortcomings, too.

    Data sampling

    Google only processes a selected sample of website activity rather than every individual data point. Rather than looking at the whole picture, it sets a threshold and selects a [hopefully] representative sample for analysis. 

    This inevitably creates gaps in data. Google attempts to fill them in using AI and machine learning, inferring the rest from data patterns. Since the results rely on assumptions and estimates, they aren’t always precise.

    In practical terms, this means that the accuracy of GA4 analysis will likely decline as website traffic increases.

    A graphic illustration of how data sampling works

    (Image source)

    Data collection limits

    GA4’s 25 million monthly events limit seems like a lot, but they add up quickly. 

    All user interactions are recorded as events, including :

    • Session start : User visits the site.
    • Page view : User loads a page (tracked automatically).
    • First visit : User accesses the site for the first time.
    • User engagement : User stays on a page for a set time period.
    • Scroll : User scrolls past 90% of the page (enhanced measurement).
    • Click : User clicks on any element (links, buttons, etc.).
    • Video start/complete : User starts or completes a video (enhanced measurement).
    • File download : User downloads a file (enhanced measurement).

    For context, consider a website averaging 50 events per session per user. If every user logs on every third day, on average, you’ll need 10,000 individual visitors a month to reach that 25 million. But that’s not the problem. 

    The problem is that collection limits in GA4 affect your ability to capture, secure, and analyse customer data effectively.

    Customisation

    GA4 users also face configuration limits that restrict their customisation options. For example : 

    • Audience limits : Since only 100 audiences are allowed, it’s necessary to combine or optimise segments rather than track too many small groups. 
    • Retention limits : Data retention is limited to only 14 months, so external storage solutions may be necessary in situations where historical data needs to be preserved.
    • Conversion events : GA4 will only track up to 30 conversion events, so it’s best to focus on high-value interactions (e.g., purchases and lead form submissions). 
    • Event-scoped dimensions : Since e-commerce operations are limited to 50 event-scoped dimensions, they need to carefully consider custom dimensions and key metrics. This makes it important to be selective about which product details to track (color, size, discount code, etc.).

    Data privacy

    GA4 isn’t GDPR-compliant out of the box. In fact, Google Analytics 4 is banned in seven EU countries because they believe the way it collects and transfers data violates GDPR.

    Data privacy regulations may or may not be a big concern, depending on where your customers are. However, if some are in the UK or any of the 30 countries that make up the European Economic Area (EEA), you must comply with the General Data Protection Regulation (GDPR). 

    It tells your customers that you don’t respect their data if you don’t. It can also get very expensive.

    Limited attribution models

    Attribution models track how different marketing touchpoints lead to a conversion (such as a purchase, sign-up, or lead generation). They help businesses understand which marketing channels and strategies are most effective in driving results.

    GA4 supports only two of the six standard attribution models previously supported in Universal Analytics. Organisations wanting data-driven or last-click attribution models will find them in Google Analytics. But they’ll need to look elsewhere if they’re going to use any of these models :

    • First click attribution
    • Linear attribution
    • Time decay attribution
    • Position-based attribution (u-shaped)

    GA360 isn’t a solution either

    Fundamentally, GA360 is the same product as GA4, without the above limits and restrictions. For companies that pay $50,000 (or more) each year, the only changes involve how much data is collected, how long it stays and data sampling thresholds.

    Above all, the GDPR-compliance issue remains. That can be a real problem for organisations with operations that collect personal data in the EEA or the UK.

    And the problem could soon be much bigger than just those 31 countries. Many countries currently implementing data privacy laws are modelling their efforts on GDPR, which may rule out both GA4 and GA360.

    Image of user customising an Matomo report and view

    What makes Matomo the top alternative ?

    No data limits

    One way to overcome all these challenges is to switch to Matomo Analytics. 

    There’s no data sampling and no data collection limits whatsoever with on-premise implementation. Matomo also supports all six attribution models, is open source and fully customisable and complies with GDPR out of the box. 

    Imagine trying to change your business strategy or marketing campaigns if you’re not confident that your data is reliable and accurate.

    It’s no secret that data sampling can negatively affect the accuracy of the data, and inaccurate data can lead to poor decision-making.

    With Matomo, there are no limits. We don’t restrict the size of containers within the Tag Manager nor the number of containers or tags within each container. You have more control over your customers’ data. 

    And you get to make your decisions based on all that data. That’s important because data quality is critical for high-impact decisions. 

    Open source

    Open-source software allows anyone to inspect, audit, and improve the source code for security and efficiency. That means no hidden data collection, faster bug fixes, and no vendor lock-in. As a bonus, these things make complying with data privacy laws and regulations easier.

    Matomo can also be modified in any way, which provides unlimited customisation possibilities. There’s also a very active developer community around Matomo, so you don’t have to make changes yourself — you can hire someone who has the technical knowledge and expertise. They can : 

    • Modify tracking scripts for advanced analytics
    • Create custom attribution models, tracking methods and dashboards
    • Integrate Matomo with any system (CRM, eCommerce, CMS, etc.)

    Data ownership

    Matomo’s open-source nature also means full data ownership. No third parties can access the data, and there’s no risk of Google using that data for ads or AI training. Furthermore, Matomo follows privacy-first tracking principles, meaning that there’s :

    • No third-party data sharing
    • Full user consent control
    • Support for cookie-less tracking
    • IP Anonymisation, by default
    • Do Not Track (DNT) support

    All of that underlines the fact that Matomo collects, stores, and tracks data 100% ethically.

    On-premise and cloud-based options

    You can use the Matomo On-Premise web analytics solution if local data privacy laws require that you store data locally. Here’s a helpful tip : many of them do. However, this might not be necessary. 

    Due to GDPR, several countries recognise the EEA as an acceptable storage location for their citizens’ data. That means servers hosted in any of those 30 countries are already compliant in terms of data location. 

    Alternatively, you could embrace modernity and choose Matomo Cloud — our servers are also in Europe. While GA4 and GA360 are cloud-based, Google’s servers are in the US, and that’s a big problem for GDPR.

    Image of a map of Europe overlaid with the universal symbol for data storage.

    Comprehensive analytics

    If you need a sophisticated web analytics platform that offers full control of your data and you have privacy concerns, Matomo is a solid choice. 

    It has built-in behavioural analytics features like HeatmapsScroll Depth and Session Recording. These tools allow you to collect and analyse data without relying on cookies or resorting to data sampling.

    Those standout features can’t be found in GA4 or GA360. Google also doesn’t offer an on-premise solution.

    The one area where Matomo can’t compete with Google Analytics is in its tight integration with the Google ecosystem : Google Ads, Gemini and Firebase. 

    Key things to consider before switching to Matomo

    There are pros and cons to switching from GA4 (or even GA360) to Matomo. That’s because no software is perfect. There are always tradeoffs somewhere. With Matomo, there are a few things to consider before switching :

    • Learning curve. Matomo is a full-featured analytics platform with many advanced features (session replay, custom event tracking, etc.). That can overwhelm new users and take time to understand well enough to maximise the benefits.
    • Technical resources. Choosing a Matomo On-Premise solution requires technical resources, such as a server and skills.
    • Third-party integration. Matomo provides pre-built integration tools for about a hundred platforms. However, it’s open source, so technical resources are required. On the plus side, it does make it possible to add to the list of APIs and connectors.

    Head-to-head : GA4 vs GA360 vs Matomo

    It’s always helpful to look at how different products stack up in terms of features and capabilities :

    GA4GA360Matomo
    Data ownership  
    Event-based data
    Session-based data  
    Unsampled data  
    Real-time data
    Heatmaps  
    Session recordings  
    A/B testing  
    Open source  
    On-premise hosting  
    Data privacySubject to Google’s data policiesSubject to Google’s data policiesGDPR, CCPA compliant ; full control over data storage
    Custom dimensionsYes (limited in free version)Yes (higher limits)Yes (unlimited in self-hosted)
    Attribution modelsLast click, data-drivenLast click, data-driven, advanced Google Ads integrationLast click, first click, linear, time decay, position-based, custom
    Data retentionUp to 14 months (free)Up to 50 monthsUnlimited (self-hosted)
    IntegrationsGoogle Ads, Search Console, BigQuery (limited in free version)Advanced integrations (Google Ads, BigQuery, Salesforce, etc.)100+ integrations (Google Ads, WordPress, Shopify, etc.)
    BigQuery exportFree (limited to 1M events/day)Free (unlimited)Paid add-on (via plugin)
    Custom reportsLimited customisationAdvanced customisationFully customisable
    ScalabilitySuitable for small to medium businessesDesigned for large enterprisesScalable without limits (self-hosted or cloud)
    Ease of useSimple, requires onboardingSteeper learning curveFlexible, setup-intensive.
    PricingFreePremium (starts at $50,000/year)Free open-source (self-hosted) ; Cloud starts at $29/month

    So, is Matomo the right solution for you ?

    That’d be a ‘yes’ if you want a Google Analytics alternative that ticks all these boxes :

    • Complies natively with privacy laws and regulations
    • Offers real-time data and custom event tracking
    • Enables a deeper understanding of user behaviour
    • Allows you to fine-tune user experiences
    • Provides full control over your customers’ data
    • Offers conversion funnels, session recordings and heatmaps
    • Has session replay to trace user interactions
    • Includes plenty of readily actionable insights

    Find out why millions of websites trust Matomo

    Matomo is an easy-to-use, all-in-one web analytics tool with advanced behavioural analytics functionality.

    It’ll also help you future-proof your business because it supports compliance with global privacy laws in 162 countries. With an ethical alternative like Matomo, you don’t need to risk your business or customers’ private data.

    It’s not just about avoiding fines. It’s also about building trust with your customers. That’s why you need a privacy-focused, ethical solution like Matomo. 

    See for yourself : download Matomo On-Premise today, or start your 21-day free trial of Matomo Cloud (no credit card required).

  • Multilingual SEO : A Marketer’s Guide to Measuring and Optimising Multilingual Websites

    26 juin, par Joe

    The web—and search engines in particular—make it easier than ever for businesses of any size to reach an international audience. 

     
    A multilingual website makes sense, especially when the majority of websites are in English. After all, you want to stand out to customers by speaking their local language. But it’s no good having a multilingual site if people can’t find it. 

    That’s where multilingual SEO comes in. 

    In this article, we’ll show you how to build a multilingual website that ranks in Google and other local search engines. You’ll learn why multilingual SEO is about more than translating your content and specific tasks you need to tick off to make your multilingual site as visible as possible. 

    ¡Vamos !

    What is multilingual SEO ? 

    Multilingual SEO is the process of optimising your website to improve search visibility in more than one language. It involves creating high-quality translations (including SEO metadata), targeting language-specific keywords and building links in the target language. 

    A definition of multilingual SEO

    The goal is to make your site as discoverable and accessible as possible for users searching Google and other search engines in their local language. 

    It’s worth pointing out that multilingual SEO differs slightly from international SEO, even if the terms are used interchangeably. With multilingual SEO, you are optimising for a language (so Spanish targets every Spanish-speaking country, not just Spain). In international SEO, you target specific countries, so you might have a different strategy for targeting Argentinian customers vs. Mexican customers. 

    Why adopt a multilingual SEO strategy ?

    There are two major reasons to adopt a multilingual SEO strategy : to reach more customers and to deliver the best experience possible. 

    Why adopt a multilingual SEO strategy

    Reach a wider audience

    Not everyone searches the web in English. Even if non-native speakers eventually resort to English, many will try Googling in their own language first. That means if you target customers in multiple non-English-speaking countries, then creating a multilingual SEO is a must to reach as many of them as possible. 

    A multilingual SEO strategy also boosts your website’s chances of appearing in country-specific search engines like Baidu and Yandex — and in localised versions of Google like Google.fr and Google.de.

    Deliver a better user experience

    Multilingual SEO gives your customers what they want : the ability to search, browse and shop in their native language. This is a big deal, with 89% of consumers saying it’s important to deal with a brand in their own language.

    Improving the user experience also increases the likelihood of non-English-speaking customers converting. As many as 82% of people won’t make a purchase in major consumer categories without local language support. 

    How to prepare for multilingual SEO success

    Before you start creating multilingual SEO content, you need to take care of a couple of things. 

    Identify target markets

    The first step is to identify the languages you want to target. You know your customers better than anyone, so it’s likely you have one or two languages in mind already. 

    But if you don’t, why not analyse your existing website traffic to discover which languages to target first ? The Locations report in Matomo (found in the Visitors section of Matomo’s navigation) shows you which countries your visitors hail from. 

    A screenshot of Matomo's Location Report

    In the example above, targeting German and Indonesian searchers would be a sensible strategy. 

    Target local keywords

    Once you’ve decided on your target markets, it’s time to find localised keywords. Keywords are the backbone of any SEO campaign, so take your time to find ones that are specific to your local markets.

    Yes, that means you shouldn’t just translate your English keywords into French or Spanish ! French or Spanish searchers may use completely different terms to find your products or services. 

    That’s why it’s vital to use a tool like Ahrefs or Semrush to do multilingual keyword research. 

    A french keyword

    This may be a bit tricky if you aren’t a native speaker of your target language, but you can translate your English keywords using Google Translate to get started. 

    Remember, search volumes won’t be as high as English keywords since fewer people are searching for them. So don’t be scared off by small keyword volumes. Besides, even in the U.S. around 95% of keywords get 10 searches per month or fewer. 

    Choose your URL structure

    The final step in preparing your multilingual SEO strategy is deciding on your URL structure, whether that’s using separate domains, subdomains or subfolders. 

    This is important for SEO as it will avoid duplicate content issues. Using language indicators within these URLs will also help both users and search engines differentiate versions of your site. 

    The first option is to have a separate domain for each target language. 

    • yoursite.com
    • yoursite.fr
    • yoursite.es

    Using subdomains would mean you keep one domain but have completely separate sites :

    • fr.yoursite.com
    • es.yoursite.com
    • de.yoursite.com

    Using subfolders keeps everything clean but can result in long URLs :

    • yoursite.com/en
    • yoursite.com/de
    • yoursite.com/es

    As you can see in the image below, we use subdomains to separate multilingual versions of you site :

    A browser showing a language-specific URL structure

    While separate domains provide more precise targeting, it’s a lot of work to manage them. So, unless you have a keyword-rich, unbranded domain name that needs translating, we’d recommend using either subdomains or subdirectories. It’s slightly easier to manage subfolders, but subdomains offer users a clearer divide between different versions of your site. 

    If you want to make your site even easier to navigate, then you can incorporate language indicators into your page’s design to make it easy for consumers to switch languages. These are the little dropdown menus you see containing various flags that let users browse in different languages.

    5 multilingual SEO strategies to use in 2024

    Now you’ve got the basics in order, use the following SEO strategies to improve your multilingual rankings. 

    Use hreflang tags

    There’s another way that Google and other search engines use to determine the language and region your website is targeting : hreflang..

    Hreflang is an HTML attribute that Google and other search engines use to ensure they serve users the right version of the page.

    You can insert it into the header section of the page like this example for a German subdomain :

    <link rel=”alternate” href=”https://yourwebsite.com/de” hreflang=”de” />

    Or you can add the relevant markup to your website’s sitemap. Here’s what the same German markup would look like :

    <xhtml:link rel=”alternate” hreflang=”de” href=”https://yourwebsite.com/de/” /> 

    Whichever method you include one language code in ISO 639-1 format. You can also include a region code in ISO 3166-1 Alpha 2 format. Note that you can include multiple region codes. A web page in German, for example, could target German and Austrian consumers. 

    Hreflang tags also avoid duplicate content issues. 

    With a multilingual site, you could have a dozen different versions of the same page, showing the same content but in a different language. Without an hreflang tag specifying that these are different versions of the same page, Google may penalise your site.

    Invest in high-quality translations

    Google rewards good content. And, while you’d hope Google Translate would be good enough, it usually isn’t.

    Instead, make sure you are using professional linguists to translate your content. They won’t only be able to produce accurate and contextually relevant translations — the kind that Google may reward with higher rankings — but they’ll also be able to account for cultural differences between languages. 

    Imagine you are translating a web page from U.S. English into Italian, for example. You’ve not only got to translate the words themselves but also the measurements (from inches to cm), dates (from mm/dd/yy to dd/mm/yy), currencies, idioms and more. 

    Translate your metadata, too

    You need to translate more than just the content of your website. You should translate its metadata — the descriptive information search engines use to understand your page — to help you rank better in Google and localised search engines. 

    As you can see in the image below, we’ve translated the French version of our homepage’s title and meta description :

    Matomo's meta data translated into French

    Page titles and meta descriptions aren’t the only pieces of metadata you need to pay attention to. Make sure you translate the following :

    • URLs
    • Image alt tags
    • Canonical tags
    • Structured data markup

    While you’re at it, make sure you have translated all of your website’s content, too. It’s easy to miss error messages, contact forms and checkout pages that would otherwise ruin the user experience. 

    Build multilingual backlinks

    Building backlinks is an important step in any SEO strategy. But it’s doubly important in multilingual SEO, where your links in your target language also help Google to understand that you have a translated website. 

    While you want to prioritise links from websites in your target language, make sure that websites are relevant to your niche. It’s no good having a link from a Spanish recipe blog if you have a marketing SaaS tool. 

    A great place to start is by mining the links of competitors in your target market. Your competitors have already done the hard work acquiring these links, and there’s every chance these websites will link to your translated content, too.

    Search competitor backlinks for multilingual link opportunities

    Don’t forget about internal linking pages in the same language, either. This will obviously help users stay in the same language while navigating your site, but it will also show Google the depth of your multilingual content.

    Monitor the SEO health of your multilingual site

    The technical performance of your multilingual pages has a significant impact on your ability to rank and convert. 

    We know for a fact that Google uses page performance metrics in the form of Core Web Vitals as a search ranking factor. What’s more, research by WP Rocker finds that a side loading in one second has a three times better conversion rate than a site loading in five seconds. 

    With that in mind, make sure your site is performing at optimal levels using Matomo’s SEO Web Vitals report. Our SEO Web Vitals feature tracks all of Google’s Core Web Vitals, including :

    • Page Speed Score
    • First Contentful Paint (FCP)
    • Final Input Delay (FID)
    • Last Contentful Paint (LCP)
    • Cumulative Layout Shift (CLS)

    The report displays each metric in a different colour depending on your site’s performance, with green meaning good, orange meaning average, and red meaning poor.

    Matomo's SEO Web Vitals Report

    Check in on these metrics regularly or set up custom alerts to automatically notify you when a specific metric drops below or exceeds a certain threshold — like if your Page Speed score falls below 50, for example. 

    How to track your multilingual SEO efforts with Matomo

    Matomo isn’t just a great tool to track your site’s SEO health ; you can also use our privacy-focused analytics platform to track your multilingual SEO success.

    For example, you could use the report to focus your multilingual SEO efforts on a single language if searches are starting to rival English. Or you decide to translate your most trafficked English keywords into your target languages, regardless if a tool like Ahrefs or Semrush tells you whether these keywords get searches or not.

    If you want to analyse the performance of your new language, for example, you can segment traffic by URL. In our case, we use the segment “Page URL contains fr.matomo.org” to measure the impact of our French website. 

    We can also track the performance of every language except French by using the segment “Page URL does not contain fr.matomo.org”.

    You can use Matomo to track your Keyword performance, too. Unlike search engine-owned platforms like Google Analytics and Google Search Console that no longer share keyword data, Matomo lets users see exactly which keywords users search to find your site in the Combined keywords report :

    Matomo's Combined Keywords Report

    This is valuable information you can use to identify new keyword opportunities and improve your multilingual content strategy. 

    For example, you could use the report to focus your multilingual SEO efforts on a single language if searches are starting to rival English. Or you decide to translate your most trafficked English keywords into your target languages, regardless if a tool like Ahrefs or Semrush tells you whether these keywords get searches or not.

    For international brands that have separate websites and apps for each target language or region, Matomo’s Roll-Up Reporting lets you keep track of aggregate data in one place. 

    A diagram that shows how Roll-up reporting works

    Roll-Up Reporting lets you view data from multiple websites and apps as if they were a single site. This lets you quickly answer questions like :

    • How many visits happened across all of my multilingual websites ?
    • Which languages contributed the most conversions ?
    • How does the performance of my Spanish app compare to my Spanish website ?

    Is it any wonder, then, that Matomo is used by over one million sites in 190 countries to track their web and SEO performance in a privacy-friendly way ?

    Join them today by trying Matomo free for 21 days, no credit card required. Alternatively, request a demo to see how Matomo can help you track your multilingual SEO efforts.