Recherche avancée

Médias (3)

Mot : - Tags -/spip

Autres articles (98)

  • Activation de l’inscription des visiteurs

    12 avril 2011, par

    Il est également possible d’activer l’inscription des visiteurs ce qui permettra à tout un chacun d’ouvrir soit même un compte sur le canal en question dans le cadre de projets ouverts par exemple.
    Pour ce faire, il suffit d’aller dans l’espace de configuration du site en choisissant le sous menus "Gestion des utilisateurs". Le premier formulaire visible correspond à cette fonctionnalité.
    Par défaut, MediaSPIP a créé lors de son initialisation un élément de menu dans le menu du haut de la page menant (...)

  • Des sites réalisés avec MediaSPIP

    2 mai 2011, par

    Cette page présente quelques-uns des sites fonctionnant sous MediaSPIP.
    Vous pouvez bien entendu ajouter le votre grâce au formulaire en bas de page.

  • Support audio et vidéo HTML5

    10 avril 2011

    MediaSPIP utilise les balises HTML5 video et audio pour la lecture de documents multimedia en profitant des dernières innovations du W3C supportées par les navigateurs modernes.
    Pour les navigateurs plus anciens, le lecteur flash Flowplayer est utilisé.
    Le lecteur HTML5 utilisé a été spécifiquement créé pour MediaSPIP : il est complètement modifiable graphiquement pour correspondre à un thème choisi.
    Ces technologies permettent de distribuer vidéo et son à la fois sur des ordinateurs conventionnels (...)

Sur d’autres sites (8799)

  • Encoding for HLS using FFMPEG results in have a decreasing DTS

    29 décembre 2014, par Luuk D. Jansen

    I am trying to encode video for HTS live streaming, but am having problems with validating the stream using Apple Media Validator (mediastreamvalidator).
    (my test file : http://dominicansinteractive.idoms.org/media/9536/playlist.m3u8)

    The output is :

    --------------------------------------------------------------------------------
    http://dominicansinteractive.idoms.org/media/9536/199/prog_index.m3u8
    --------------------------------------------------------------------------------

    Playlist Validation:

       OK

    Segments:

    segment_00000.ts:

       ERROR: (-1) Decreasing DTS were detected in track 0
       ERROR: (-1) Decreasing DTS were detected in track 1

       Average segment duration: 8.07 seconds
       Average segment bitrate: 2155094.67 bps
       Average segment structural overhead: 206525.83 bps (9.58 %)

    The second segment doesn’t seem to have the problem :

    [mpegts @ 0x1d78120] Format mpegts probed with size=2048 and score=100
    [mpegts @ 0x1d78120] stream=0 stream_type=1b pid=100 prog_reg_desc=
    [mpegts @ 0x1d78120] stream=1 stream_type=f pid=101 prog_reg_desc=
    [mpegts @ 0x1d78120] File position before avformat_find_stream_info() is 0
    [h264 @ 0x1d7c1c0] Current profile doesn't provide more RBSP data in PPS, skipping
    [h264 @ 0x1d7c1c0] no picture
    [h264 @ 0x1d7c1c0] Current profile doesn't provide more RBSP data in PPS, skipping
      Last message repeated 3 times
    [mpegts @ 0x1d78120] max_analyze_duration 5000000 reached at 5013333
    [mpegts @ 0x1d78120] File position after avformat_find_stream_info() is 0

    This seems to be a serious problem for HLS, so I am looking if there is a way to fix this.

    When looking with FFMPEG at the encoded file I get (encoder output/command at the bottom of the email) :

    ffmpeg -loglevel 99 -i encoded.ts
    ffmpeg version N-37783-gdf3a96c Copyright (c) 2000-2012 the FFmpeg developers
    built on Jul  4 2012 07:44:52 with gcc 4.4.5
    configuration: --enable-gpl --enable-version3 --enable-nonfree --enable-libfaac --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libmp3lame --enable-libtheora --enable-libvorbis --enable-libx264 --enable-libvpx --enable-libfaac --enable-nonfree
    libavutil      51. 63.100 / 51. 63.100
    libavcodec     54. 32.100 / 54. 32.100
    libavformat    54. 14.100 / 54. 14.100
    libavdevice    54.  0.100 / 54.  0.100
    libavfilter     3.  0.101 /  3.  0.101
    libswscale      2.  1.100 /  2.  1.100
    libswresample   0. 15.100 /  0. 15.100
    libpostproc    52.  0.100 / 52.  0.100
    [mpegts @ 0x2023120] Format mpegts probed with size=2048 and score=100
    [mpegts @ 0x2023120] stream=0 stream_type=1b pid=100 prog_reg_desc=
    [mpegts @ 0x2023120] stream=1 stream_type=f pid=101 prog_reg_desc=
    [mpegts @ 0x2023120] File position before avformat_find_stream_info() is 0
    [h264 @ 0x20271c0] Current profile doesn't provide more RBSP data in PPS, skipping
    [h264 @ 0x20271c0] no picture
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 143280 in que
      Last message repeated 6 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 158640 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 175920 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 193200 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 210480 in que
      Last message repeated 7 times
    [h264 @ 0x20271c0] Current profile doesn't provide more RBSP data in PPS, skipping
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 227760 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 245040 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 262320 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 279600 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 296880 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 314160 in que
      Last message repeated 7 times
    [h264 @ 0x20271c0] Current profile doesn't provide more RBSP data in PPS, skipping
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 331440 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 348720 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 366000 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 383280 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 400560 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 417840 in que
      Last message repeated 6 times
    [h264 @ 0x20271c0] Current profile doesn't provide more RBSP data in PPS, skipping
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 433200 in que
      Last message repeated 6 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 448560 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 465840 in que
      Last message repeated 6 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 481200 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 498480 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 515760 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 533040 in que
      Last message repeated 6 times
    [h264 @ 0x20271c0] Current profile doesn't provide more RBSP data in PPS, skipping
    [mpegts @ 0x2023120] first_dts 124080 not matching first dts 548400 in que
      Last message repeated 7 times
    [mpegts @ 0x2023120] max_analyze_duration 5000000 reached at 5000000
    [mpegts @ 0x2023120] File position after avformat_find_stream_info() is 0

    And when at the first segmented file:
    ffmpeg -loglevel 99 -i segment_00000.ts
    ffmpeg version N-37783-gdf3a96c Copyright (c) 2000-2012 the FFmpeg developers
    built on Jul  4 2012 07:44:52 with gcc 4.4.5
    configuration: --enable-gpl --enable-version3 --enable-nonfree --enable-libfaac --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libmp3lame --enable-libtheora --enable-libvorbis --enable-libx264 --enable-libvpx --enable-libfaac --enable-nonfree
    libavutil      51. 63.100 / 51. 63.100
    libavcodec     54. 32.100 / 54. 32.100
    libavformat    54. 14.100 / 54. 14.100
    libavdevice    54.  0.100 / 54.  0.100
    libavfilter     3.  0.101 /  3.  0.101
    libswscale      2.  1.100 /  2.  1.100
    libswresample   0. 15.100 /  0. 15.100
    libpostproc    52.  0.100 / 52.  0.100
    [mpegts @ 0x1a0b120] Format mpegts probed with size=2048 and score=100
    [mpegts @ 0x1a0b120] stream=0 stream_type=1b pid=100 prog_reg_desc=
    [mpegts @ 0x1a0b120] stream=1 stream_type=f pid=101 prog_reg_desc=
    [mpegts @ 0x1a0b120] File position before avformat_find_stream_info() is 0
    [mpegts @ 0x1a0b120] Invalid timestamps stream=0, pts=1920, dts=8589929312, size=2355
    [mpegts @ 0x1a0b120] Invalid timestamps stream=0, pts=16320, dts=8589932912, size=3203
    [h264 @ 0x1a0f1c0] Current profile doesn't provide more RBSP data in PPS, skipping
    [h264 @ 0x1a0f1c0] no picture
    [h264 @ 0x1a0f1c0] Current profile doesn't provide more RBSP data in PPS, skipping
      Last message repeated 3 times
    [mpegts @ 0x1a0b120] max_analyze_duration 5000000 reached at 5013333
    [mpegts @ 0x1a0b120] File position after avformat_find_stream_info() is 0

    This problem does not occur with the BASELINE profile, but does with MAIN.

    The command I use for encoding is :

    ffmpeg, -i, [path]/test.mov, -y, -f, mpegts, -acodec, aac, -strict, -2, -ar, 48000, -b:a, 128000, -s, 960x540, -vcodec, libx264, -b:v, 1200000, -aspect, 960:540, -r, 25, -level, 3.1, -vprofile, main, -flags, +loop, -cmp, +chroma, -partitions, +parti4x4+partp8x8+partb8x8, -subq, 5, -trellis, 1, -refs, 1, -coder, 0, -me_range, 16, -keyint_min, 25, -sc_threshold, 40, -i_qfactor, 0.71, -bt, 200k, -maxrate, 1200000, -bufsize, 1200000, -rc_eq, 'blurCplx^(1-qComp)', -qcomp, 0.6, -qmin, 10, -qmax, 51, -qdiff, 4, -level, 30, -g, 30, -async, 2, [path]/encoded.ts

    08:40:29,843 DEBUG ~ FFMPEG(1):   libavutil      51. 63.100 / 51. 63.100
    08:40:29,843 DEBUG ~ FFMPEG(1):   libavcodec     54. 32.100 / 54. 32.100
    08:40:29,843 DEBUG ~ FFMPEG(1):   libavformat    54. 14.100 / 54. 14.100
    08:40:29,843 DEBUG ~ FFMPEG(1):   libavdevice    54.  0.100 / 54.  0.100
    08:40:29,843 DEBUG ~ FFMPEG(1):   libavfilter     3.  0.101 /  3.  0.101
    08:40:29,844 DEBUG ~ FFMPEG(1):   libswscale      2.  1.100 /  2.  1.100
    08:40:29,844 DEBUG ~ FFMPEG(1):   libswresample   0. 15.100 /  0. 15.100
    08:40:29,844 DEBUG ~ FFMPEG(1):   libpostproc    52.  0.100 / 52.  0.100
    08:40:30,033 DEBUG ~ FFMPEG(1): Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '[path]/test.mov':
    08:40:30,033 DEBUG ~ FFMPEG(1):   Metadata:
    08:40:30,033 DEBUG ~ FFMPEG(1):     major_brand     : qt  
    08:40:30,033 DEBUG ~ FFMPEG(1):     minor_version   : 537199360
    08:40:30,035 DEBUG ~ FFMPEG(1):     compatible_brands: qt  
    08:40:30,035 DEBUG ~ FFMPEG(1):     creation_time   : 2011-12-05 10:54:24
    08:40:30,036 DEBUG ~ FFMPEG(1):     timecode        : 00:00:00:00
    08:40:30,036 DEBUG ~ FFMPEG(1):   Duration: 00:00:24.20, start: 0.000000, bitrate: 9912 kb/s
    08:40:30,037 DEBUG ~ FFMPEG(1):     Stream #0:0(eng): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1920x1080, 9777 kb/s, 25 fps, 25 tbr, 25 tbn, 50 tbc
    08:40:30,037 DEBUG ~ FFMPEG(1):     Metadata:
    08:40:30,037 DEBUG ~ FFMPEG(1):       creation_time   : 2011-12-05 10:56:28
    08:40:30,037 DEBUG ~ FFMPEG(1):       handler_name    : Apple Video Media Handler
    08:40:30,038 DEBUG ~ FFMPEG(1):     Stream #0:1(eng): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, s16, 129 kb/s
    08:40:30,038 DEBUG ~ FFMPEG(1):     Metadata:
    08:40:30,038 DEBUG ~ FFMPEG(1):       creation_time   : 2011-12-05 10:56:28
    08:40:30,038 DEBUG ~ FFMPEG(1):       handler_name    : Apple Sound Media Handler
    08:40:30,038 DEBUG ~ FFMPEG(1):     Stream #0:2(eng): Data: none (tmcd / 0x64636D74)
    08:40:30,038 DEBUG ~ FFMPEG(1):     Metadata:
    08:40:30,038 DEBUG ~ FFMPEG(1):       creation_time   : 2011-12-05 10:56:28
    08:40:30,039 DEBUG ~ FFMPEG(1):       handler_name    : Time Code Media Handler
    08:40:30,039 DEBUG ~ FFMPEG(1):       timecode        : 00:00:00:00
    08:40:30,092 DEBUG ~ FFMPEG(1): [graph 0 input from stream 0:0 @ 0x1c17180] w:1920 h:1080 pixfmt:yuv420p tb:1/25 fr:25/1 sar:0/1 sws_param:flags=2
    08:40:30,092 DEBUG ~ FFMPEG(1): [output stream 0:0 @ 0x1c033a0] No opaque field provided
    08:40:30,110 DEBUG ~ FFMPEG(1): [scaler for output stream 0:0 @ 0x1c18040] w:1920 h:1080 fmt:yuv420p sar:0/1 -> w:960 h:540 fmt:yuv420p sar:0/1 flags:0x4
    08:40:30,110 DEBUG ~ FFMPEG(1): [graph 1 input from stream 0:1 @ 0x1c53440] tb:1/48000 samplefmt:s16 samplerate:48000 chlayout:0x3
    08:40:30,110 DEBUG ~ FFMPEG(1): -async is forwarded to lavfi similarly to -af aresample=min_comp=0.001:min_hard_comp=0.100000:max_soft_comp=0.000042.
    08:40:30,122 DEBUG ~ FFMPEG(1): [graph 1 aresample for input stream 0:1 @ 0x1c36880] chl:stereo fmt:s16 r:48000Hz -> chl:stereo fmt:flt r:48000Hz
    08:40:30,142 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] using SAR=1/1
    08:40:30,142 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] frame MB size (60x34) > level limit (1620)
    08:40:30,142 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] DPB size (4 frames, 3133440 bytes) > level limit (3 frames, 3110400 bytes)
    08:40:30,142 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] MB rate (51000) > level limit (40500)
    08:40:30,170 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] using cpu capabilities: MMX2 SSE2Slow SlowCTZ
    08:40:30,182 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] profile Main, level 3.0
    08:40:30,235 DEBUG ~ FFMPEG(1): [mpegts @ 0x1be3540] muxrate VBR, pcr every 2 pkts, sdt every 200, pat/pmt every 40 pkts
    08:40:30,235 DEBUG ~ FFMPEG(1): Output #0, mpegts, to '[path]/encoded.ts':
    08:40:30,235 DEBUG ~ FFMPEG(1):   Metadata:
    08:40:30,235 DEBUG ~ FFMPEG(1):     major_brand     : qt  
    08:40:30,235 DEBUG ~ FFMPEG(1):     minor_version   : 537199360
    08:40:30,235 DEBUG ~ FFMPEG(1):     compatible_brands: qt  
    08:40:30,235 DEBUG ~ FFMPEG(1):     timecode        : 00:00:00:00
    08:40:30,235 DEBUG ~ FFMPEG(1):     encoder         : Lavf54.14.100
    08:40:30,235 DEBUG ~ FFMPEG(1):     Stream #0:0(eng): Video: h264, yuv420p, 960x540 [SAR 1:1 DAR 16:9], q=10-51, 1200 kb/s, 90k tbn, 25 tbc
    08:40:30,235 DEBUG ~ FFMPEG(1):     Metadata:
    08:40:30,235 DEBUG ~ FFMPEG(1):       creation_time   : 2011-12-05 10:56:28
    08:40:30,235 DEBUG ~ FFMPEG(1):       handler_name    : Apple Video Media Handler
    08:40:30,236 DEBUG ~ FFMPEG(1):     Stream #0:1(eng): Audio: aac, 48000 Hz, stereo, flt, 128 kb/s
    08:40:30,236 DEBUG ~ FFMPEG(1):     Metadata:
    08:40:30,236 DEBUG ~ FFMPEG(1):       creation_time   : 2011-12-05 10:56:28
    08:40:30,236 DEBUG ~ FFMPEG(1):       handler_name    : Apple Sound Media Handler
    08:40:30,236 DEBUG ~ FFMPEG(1): Stream mapping:
    08:40:30,236 DEBUG ~ FFMPEG(1):   Stream #0:0 -> #0:0 (h264 -> libx264)
    08:40:30,236 DEBUG ~ FFMPEG(1):   Stream #0:1 -> #0:1 (aac -> aac)

    [...]

    08:40:55,398 DEBUG ~ FFMPEG(1): video:3121kB audio:359kB subtitle:0 global headers:0kB muxing overhead 11.132085%
    08:40:55,407 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] frame I:21    Avg QP:21.57  size: 88153
    08:40:55,407 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] frame P:233   Avg QP:22.74  size:  5560
    08:40:55,407 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] frame B:351   Avg QP:27.45  size:   141
    08:40:55,407 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] consecutive B-frames: 21.7%  2.0%  3.0% 73.4%
    08:40:55,407 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] mb I  I16..4: 54.5%  0.0% 45.5%
    08:40:55,422 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] mb P  I16..4:  4.7%  0.0%  1.3%  P16..4: 24.6%  3.5%  0.8%  0.0%  0.0%    skip:65.1%
    08:40:55,422 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] mb B  I16..4:  0.1%  0.0%  0.1%  B16..8:  0.5%  0.1%  0.0%  direct: 0.6%  skip:98.6%  L0:32.3% L1:47.1% BI:20.6%
    08:40:55,422 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] coded y,uvDC,uvAC intra: 59.4% 5.8% 0.4% inter: 5.4% 3.0% 0.0%
    08:40:55,422 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] i16 v,h,dc,p: 58% 16% 21%  4%
    08:40:55,422 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 20% 21% 17%  5% 10%  7%  5%  5% 10%
    08:40:55,422 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] i8c dc,h,v,p: 94%  3%  3%  0%
    08:40:55,422 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] Weighted P-Frames: Y:13.7% UV:3.4%
    08:40:55,422 DEBUG ~ FFMPEG(1): [libx264 @ 0x1be3cc0] kb/s:1056.61

    For segmenting is :

    ffmpeg, -i,[path]encoded.ts, -y, -c, copy, -flags, global_header, -map, 0, -f, segment, -segment_time, 10, -segment_list, [path]/fileList.txt, -segment_format, mpegts, [path]/segment_%05d.ts]

    Any help would really be appreciated !

  • ffmpeg : need for speed

    21 juillet 2012, par roufamatic

    I am using ffmpeg to convert a set of images (bmps) with an audio track into Web ready video. Target formats are h.264 mp4, webm and flv.
    This is on a Windows Azure extra-large instance (8 proc) using the prebuilt zeranoe static builds ( http://ffmpeg.zeranoe.com/builds/).

    Suppose I'm willing to sacrifice quality and size for raw speed. What options for each format will yield the quickest result ?

    My "baseline" command looks like this (swap the extension for the other formats) :

    ffmpeg -y -i frames%5d.bmp -i audio.mp3 -r 23.97 out.mp4

    I can change the inputs to other formats if needed (jpg images, aac audio, etc).

  • Adding A New System To The Game Music Website

    1er août 2012, par Multimedia Mike — General

    At first, I was planning to just make a little website where users could install a Chrome browser extension and play music from old 8-bit NES games. But, like many software projects, the goal sort of ballooned. I created a website where users can easily play old video game music. It doesn’t cover too many systems yet, but I have had individual requests to add just about every system you can think of.

    The craziest part is that I know it’s possible to represent most of the systems. Eventually, it would be great to reach Chipamp parity (a combination plugin for Winamp that packages together plugins for many of these chiptunes). But there is a process to all of this. I have taken to defining a number of phases that are required to get a new system covered.

    Phase 0 informally involves marveling at the obscurity of some of the console systems for which chiptune collections have evolved. WonderSwan ? Sharp X68000 ? PC-88 ? I may be viewing this through a terribly Ameri-centric lens. I’ve at least heard of the ZX Spectrum and the Amstrad CPC even if I’ve never seen either.

    No matter. The goal is to get all their chiptunes cataloged and playable.

    Phase 1 : Finding A Player
    The first step is to find a bit of open source code that can play a particular format. If it’s a library that can handle many formats, like Game Music Emu or Audio Overload SDK, even better (probably). The specific open source license isn’t a big concern for me. I’m almost certain that some of the libraries that SaltyGME currently mixes are somehow incompatible, license-wise. I’ll worry about it when I encounter someone who A) cares, and B) is in a position to do something about it. Historical preservation comes first, and these software libraries aren’t getting any younger (I’m finding some that haven’t been touched in a decade).

    Phase 2 : Test Program
    The next phase is to create a basic test bench program that sends a music file into the library, generates a buffer of audio, and shoves it out to the speakers via PulseAudio’s simple API (people like to rip on PulseAudio, but its simple API really lives up to its name and requires pages less boilerplate code to play a few samples than ALSA).

    Phase 3 : Plug Into Web Player
    After successfully creating the test bench and understanding exactly which source files need to be built, the next phase is to hook it up to the main SaltyGME program via the ad-hoc plugin API I developed. This API requires that a player backend can, at the very least, initialize itself based on a buffer of bytes and generate audio samples into an array of 16-bit numbers. The API also provides functions for managing files with multiple tracks and toggling individual voices/channels if the library supports such a feature. Having the test bench application written beforehand usually smooths out this step.

    But really, I’m just getting started.

    Phase 4 : Collecting A Song Corpus
    Then there is the matter of staging a collection of songs for a given system. It seems like it would just be a matter of finding a large collection of songs for a given format, downloading them in bulk, and mirroring them. Honestly, that’s the easy part. People who are interested in this stuff have been lovingly curating massive collections of these songs for years (see SNESmusic.org for one of the best examples, and they also host a torrent of all their music for really quick and easy hoarding).

    In my drive to make this game music website more useful for normal people, the goal is to extract as much metadata as possible to make searching better, and to package the data so that it’s as convenient as possible for users. Whenever I seek to add a new format to the collection, this is the phase where I invariably find that I have to fundamentally modify some of the assumptions I originally made in the player.

    First, there were the NES Sound Format (NSF) files, the original format I wanted to play. These are files that have any number of songs packed into a single file. Playback libraries expose APIs to jump to individual tracks. So the player was designed around that. Game Boy GBS files also fall into this category but present a different challenge vis-à-vis metadata, addressed in the next phase.

    Then, there were the SPC files. Each SPC file is its own song and multiple SPC files are commonly bundled as RAR files. Not wanting to deal with RAR, or any format where I interacted with a general compression API to pull a few files out, I created a custom resource format (inspired by so many I have studied and documented) and compressed it with a simpler compression API. I also had to modify some of the player’s assumptions to deal with this archive format. Genesis VGMs, bundled either in .zip or .7z, followed the same model as SPC in RAR.

    Then it was suggested that I attempt to bring SaltyGME closer to feature parity with Chipamp, rather than just being a Chrome browser frontend for Game Music Emu. When I studied the Portable Sound Format (PSF), I realized it didn’t fit into the player model I already had. PSF uses a sort of shared library model for code execution and I developed another resource archive format to cope with it. So that covers quite a few formats.

    One more architecture challenge arose when I started to study one of the prevailing metadata formats, explained in the next phase.

    Phase 5 : Metadata
    Finally, for the collections to really be useful, I need to harvest that juicy metadata for search and presentation.

    I have created a series of programs and scripts to scrape metadata out of these music files and store it all in a database that drives the website and search engine. I recognize that it’s no good to have a large corpus of songs with minimal metadata and while importing bulk quantities of music, the scripts harshly reject songs that have too little metadata.

    Again, challenges abound. One of the biggest challenges I’m facing is the peculiar quasi-freeform metadata format that emerged as .m3u that takes a form similar to :

    #################################################################
    #
    # GRADIUS2
    # (c) KONAMI  by Furukawa Motoaki, IKACHAN
    #
    #################################################################
    

    nemesis2.kss::KSS,62,[Nemesis2] (Opening),2:23,,0
    nemesis2.kss::KSS,61,[Nemesis2] (Start),7,,0
    nemesis2.kss::KSS,43,[Nemesis2] (Air Battle),34,0-
    nemesis2.kss::KSS,44,[Nemesis2] (1st. BGM),51,0-
    [...]

    A lot of file formats (including Game Boy GBS mentioned earlier) store their metadata separately using this format. I have some ideas about tools I can use to help me process this data but I’m pretty sure each one will require some manual intervention.

    As alluded to in phase 4, .m3u presents another architectural challenge : Notice the second field in the CSV .m3u data. That’s a track number. A player can’t expect every track in a bundled chiptune file to be valid, nor to be in any particular order. Thus, I needed to alter the architecture once more to take this into account. However, instead of modifying the SaltyGME player, I simply extended the metadata database to include a playback order which, by default, is the same as the track order but can also accommodate this new issue. This also has the bonus of providing a facility to exclude playback of certain tracks. This comes in handy for many PSF archives which tend to include files that only provide support for other files and aren’t meant to be played on their own.

    Bright Side
    The reward for all of this effort is that the data lands in a proper database in the end. None of it goes back into the chiptune files themselves. This makes further modification easier as all of the data that is indexed and presented on the site comes from the database. Somewhere down the road, I should probably create an API for accessing this metadata.