From Wikimedia Commons, the free media repository
Jump to navigation Jump to search

Xeno-canto birdsong (background discussion copied from Village Pump)[edit]

The website xeno-canto is a repository of good quality bird song recordings, almost 400 of which [1] are cc-by-sa. It also allows contributors to remove their contribution at any time. Do we, or could we, have a tool or bot for importing files from there? Andy Mabbett (talk) 13:04, 7 January 2013 (UTC)

Hi Andy, these are quite delightful. I don't know of an easy tool to use for this. I am taking a look, but as a back-burner task to fiddle around with using my Python muscles, and create some modules that I might reuse for another custom upload. I might stutter due to the pressure of other stuff going on but I'll contact you if I run into a brick wall.
After reviewing the website a little, it would be (relatively) straightforward to scrape the data but loading these to Commons seems the sort of re-use that their project is set up for. Rather than just going on a hack raid, I'll try writing to the project first and checking if they have an API I can use, this might help if we want to refresh in the future.
Update they have a csv service, but this appears strictly limited to queries by species, not quite what is needed here.
Oh, and of course, Commons cannot take mp3 files, so these would need to be batch re-encoded to ogg format.
I have created an initial upload example which only uses the data from the file page on, and so could be easily automatically created. See File:Nothoprocta pentlandii - Andean Tinamou - XC112728.ogg. The Latin names are particularly useful for automatic categorization, so can nicely be played from within Category:Nothoprocta pentlandi where the user can be looking at photographs of the bird at the same time. -- (talk) 12:53, 16 January 2013 (UTC)

Project brief[edit]

  1. Capture the list of source file references/links from xeno-canto with CC-BY-SA licenses
  2. Download the mp3 files locally
  3. Batch reencode to ogg format
  4. Scrape the file information from xeno-canto for each audio file
  5. Batch upload the ogg files with file information to Wikimedia Commons
  6. Design a report to check which files released in the future on xeno-canto are not already on Commons

Step 1 - Capture the list[edit]

I have a bit of python than will now churn through the CC-BY-SA query at any time and dump a new file list. It's quick, it seems to take about 10 seconds to run. Captured the current result below.

xeno-canto files with CC-BY-SA licences as of 2013-01-16
(0) XC112728
(1) XC112727
(2) XC109825
(3) XC109664
(4) XC104533
(5) XC104532
(6) XC61517
(7) XC115583
(8) XC83152
(9) XC96532
(10) XC62259
(11) XC96531
(12) XC63109
(13) XC101287
(14) XC112828
(15) XC62258
(16) XC114233
(17) XC101288
(18) XC99573
(19) XC107690
(20) XC109391
(21) XC109541
(22) XC108658
(23) XC83153
(24) XC74741
(25) XC112711
(26) XC71575
(27) XC101582
(28) XC77877
(29) XC111114
(30) XC111155
(31) XC111154
(32) XC111153
(33) XC109542
(34) XC102973
(35) XC113756
(36) XC111491
(37) XC111490
(38) XC111489
(39) XC99570
(40) XC99571
(41) XC109656
(42) XC62728
(43) XC78342
(44) XC99969
(45) XC104531
(46) XC109659
(47) XC109658
(48) XC109657
(49) XC75111
(50) XC82758
(51) XC112747
(52) XC80747
(53) XC75829
(54) XC103418
(55) XC105129
(56) XC109598
(57) XC109597
(58) XC109852
(59) XC109651
(60) XC99550
(61) XC110258
(62) XC79968
(63) XC71728
(64) XC78062
(65) XC109667
(66) XC110974
(67) XC78061
(68) XC76080
(69) XC115432
(70) XC115431
(71) XC78888
(72) XC104536
(73) XC104537
(74) XC71727
(75) XC61518
(76) XC112730
(77) XC112729
(78) XC112726
(79) XC113246
(80) XC112734
(81) XC112732
(82) XC112731
(83) XC112736
(84) XC112722
(85) XC112721
(86) XC112713
(87) XC112712
(88) XC112725
(89) XC112724
(90) XC99544
(91) XC99547
(92) XC109603
(93) XC109602
(94) XC86752
(95) XC78886
(96) XC105928
(97) XC81301
(98) XC78890
(99) XC101616
(100) XC104535
(101) XC104534
(102) XC112746
(103) XC102967
(104) XC101615
(105) XC78870
(106) XC78883
(107) XC78882
(108) XC102965
(109) XC102966
(110) XC104529
(111) XC77879
(112) XC102969
(113) XC102968
(114) XC102286
(115) XC80735
(116) XC78885
(117) XC78884
(118) XC109601
(119) XC86756
(120) XC86755
(121) XC108404
(122) XC81291
(123) XC109654
(124) XC110262
(125) XC110261
(126) XC110259
(127) XC109653
(128) XC110976
(129) XC112829
(130) XC112598
(131) XC69128
(132) XC115429
(133) XC110263
(134) XC80525
(135) XC91560
(136) XC110257
(137) XC101590
(138) XC107623
(139) XC86750
(140) XC114086
(141) XC86760
(142) XC70185
(143) XC77884
(144) XC109655
(145) XC109595
(146) XC109857
(147) XC109665
(148) XC99549
(149) XC82759
(150) XC83449
(151) XC114614
(152) XC109666
(153) XC109853
(154) XC109854
(155) XC111113
(156) XC93427
(157) XC106012
(158) XC106011
(159) XC106010
(160) XC62608
(161) XC108481
(162) XC105805
(163) XC105804
(164) XC109856
(165) XC109668
(166) XC109632
(167) XC109604
(168) XC86753
(169) XC79974
(170) XC78892
(171) XC59832
(172) XC86751
(173) XC78876
(174) XC104516
(175) XC78341
(176) XC104518
(177) XC86754
(178) XC91412
(179) XC86757
(180) XC81292
(181) XC79975
(182) XC78887
(183) XC81306
(184) XC81305
(185) XC109834
(186) XC109833
(187) XC109832
(188) XC109831
(189) XC109829
(190) XC109827
(191) XC109826
(192) XC79976
(193) XC100032
(194) XC78880
(195) XC78879
(196) XC78881
(197) XC105131
(198) XC105133
(199) XC112741
(200) XC112745
(201) XC112744
(202) XC75498
(203) XC112597
(204) XC107523
(205) XC75499
(206) XC114615
(207) XC86749
(208) XC111043
(209) XC111042
(210) XC111041
(211) XC111040
(212) XC77573
(213) XC70423
(214) XC118266
(215) XC59665
(216) XC118265
(217) XC115596
(218) XC115599
(219) XC115598
(220) XC115597
(221) XC115595
(222) XC99546
(223) XC77883
(224) XC78877
(225) XC77882
(226) XC78891
(227) XC101292
(228) XC101290
(229) XC78871
(230) XC78063
(231) XC105134
(232) XC86759
(233) XC86758
(234) XC101611
(235) XC80734
(236) XC62257
(237) XC78878
(238) XC101593
(239) XC79972
(240) XC77881
(241) XC101592
(242) XC78893
(243) XC77880
(244) XC101589
(245) XC101588
(246) XC77878
(247) XC101612
(248) XC101581
(249) XC101580
(250) XC78064
(251) XC81303
(252) XC81302
(253) XC101584
(254) XC101587
(255) XC101586
(256) XC101585
(257) XC101583
(258) XC61892
(259) XC78058
(260) XC78057
(261) XC101293
(262) XC101591
(263) XC109599
(264) XC78875
(265) XC109600
(266) XC108402
(267) XC102970
(268) XC101614
(269) XC81300
(270) XC99574
(271) XC102972
(272) XC99548
(273) XC81290
(274) XC82755
(275) XC75497
(276) XC78889
(277) XC75495
(278) XC104521
(279) XC104520
(280) XC82756
(281) XC77876
(282) XC99545
(283) XC81304
(284) XC104524
(285) XC104523
(286) XC104522
(287) XC76505
(288) XC62943
(289) XC78060
(290) XC78059
(291) XC109669
(292) XC99569
(293) XC80524
(294) XC75500
(295) XC81951
(296) XC115581
(297) XC99572
(298) XC77875
(299) XC110975
(300) XC109855
(301) XC104514
(302) XC104512
(303) XC104511
(304) XC97211
(305) XC97210
(306) XC96803
(307) XC82760
(308) XC104530
(309) XC81296
(310) XC81295
(311) XC81294
(312) XC81293
(313) XC115594
(314) XC115430
(315) XC92009
(316) XC76506
(317) XC81201
(318) XC79970
(319) XC102971
(320) XC81299
(321) XC102964
(322) XC102963
(323) XC102962
(324) XC102961
(325) XC102960
(326) XC109661
(327) XC109652
(328) XC104528
(329) XC104527
(330) XC109662
(331) XC109660
(332) XC104526
(333) XC81298
(334) XC81297
(335) XC78874
(336) XC110260
(337) XC109663
(338) XC113791
(339) XC112743
(340) XC112739
(341) XC112718
(342) XC112717
(343) XC112716
(344) XC112720
(345) XC112719
(346) XC112748
(347) XC112715
(348) XC112714
(349) XC112723
(350) XC82764
(351) XC82763
(352) XC82762
(353) XC82761
(354) XC102287
(355) XC79967
(356) XC77572
(357) XC112830
(358) XC75501
(359) XC71726
(360) XC112749
(361) XC59831
(362) XC108501
(363) XC108499
(364) XC82757

Step 2 - Download[edit]

A slight tweak to the listing script and now I have all the files downloaded as local mp3 files. It was quick again, around about 2 seconds per file or less. The total downloaded was 246mb.

Step 3 - encode mp3 -> ogg[edit]

This was more of a problem on my old macmini than I thought and I failed to get batch processing to work after several attempts. Fortunately wolfgang42 offered to lend a hand with batch processing the files (with the help of dropbox and wikisend to share them) and these are now ready for upload.

Second round of encoding[edit]

Unfortunately around half of the files had some sort of apparent glitch with the ogg encoding, making them playback online at double speed (possibly an issue with the built in player on Commons). A new encoding of the mp3 files using ffmpeg2theora at high quality and then a new batch upload for all those identified in Category:Xeno-canto (check needed) is required.

Step 4 & 5 - scraping the file information, uploading[edit]

Using the id numbers, grab the metadata to populate the information box, location data, categories and set the best title.

This seems to be running well apart from the sort of teething problems one might expect as I have never done a batch upload using my own Python scripts rather than other bots before. Based on Andy's edit I am using {{Species-inline}} for the scientific and vernacular names and I decided against repeating the Latitude and Longitude when I am also adding {{Location dec}}.

As I am uploading from a macmini, I ran into the file connection problem and had to (temporarily) set my file to avoid connection timeouts. I also could not work out how to set the edit message on upload, so the default is being used (wikipedia.setAction() seemed to make no difference to upload.UploadRobot()). Being cautious, I am uploading at a maximum rate of 2 per minute.

I had assumed that files would have coordinates, but some do not as it turns out. This generates a bit of naff code - {{Location dec|<span class='unspecified'>Not specified</span>|<span class='unspecified'>Not specified</span>}} - which I will hook out when the upload is finished using VisualFileChange as I expect this to be a relatively small number. I have set an error trap in the script in case it is used to add future uploads.

A second problem showed itself in Location data with Paraná State as the non-ascii text caused the script to halt. I had to add an encoding for location which may display poorly for some files, though the encoding will give a clue as to the characters needed. For example this diff.

Step 6 - maintenance[edit]

I will defer putting this together until there are a fresh lot of files on xeno-canto with a CC-BY-SA licence to worry about. I have the routines now to pull the live list of relevant id numbers from XC and from the category on Commons, so creating a script to show the difference should not be too big a deal.

By the way, there are now about 250 more BY-SA files available on XC, so it might be worth doing another import? Jnthnjng (talk) 16:40, 18 July 2013 (UTC)
  • Thanks for the prompt. I did take a brief look at this a month ago. I know a lot more about how to go about this now, having worked on several other batch upload projects. I would like to create a more stable routine that I can re-run to upload new files without any re-programming. I'll put it on my backlog, so I'll probably re-visit this in a month or so and have a program that can run every month without much hassle. :-) -- (talk) 17:25, 18 July 2013 (UTC)
  • I have decided to rewrite this from scratch. It's a bit of hassle for a few hundred more files, but repeatability and the ability to re-encode to ogg on the fly, seems worth it to me. Rather than scraping the website, I will pull in the JSON array from the API (hopefully it will stay available) and then do existence/duplicate checks for each file based on the XC number rather than any filesize or hash, as due to the ogg recoding this may be unreliable. For anyone reviewing this, the JSON records contain info in the form:
{ u'cnt': u'Argentina',
  u'en': u'Andean Tinamou',
  u'file': u'',
  u'gen': u'Nothoprocta',
  u'id': u'112728',
  u'lat': u'-25.2001',
  u'lic': u'',
  u'lng': u'-65.8167',
  u'loc': u'Finca El Candado, Salta',
  u'rec': u'Niels Krabbe',
  u'sp': u'pentlandii',
  u'type': u'song',
  u'url': u''}
✓ Done I managed to fit this in before taking a break. 290 files uploaded. The new routine can be re-run at any time for automatic updates and left to suck in the JSON array, filter out existing files and upload with ogg coversions on the fly. I am now losslessly converting with the maximum quality setting for the ogg files (q=10), meaning they are slightly larger that the mp3 "originals". I noticed 2 files where the identification had changed at source, so the "duplicate" test now only identifies a match if genus, species and XC-number are the same (see Commons:Deletion requests/File:Butorides virescens - Green Heron - XC107690.ogg and File:Carpodacus mexicanus frontalis - House Finch - XC99546.ogg). This way, if the species identification changes on XC, there will be a new upload (which we could later pick out by searching for duplicate id numbers). I was slightly worried that we may be getting false matches of the type XC12345 being a substring of XC123456, checking the genus and species makes this far less likely to be a problem. -- (talk) 07:07, 24 July 2013 (UTC)
By the way, the XC API is now finalized and documented. Unfortunately the output format has also changed (but only very slightly). You can find full documentation here. Sorry for the inconvenience. Jnthnjng (talk) 14:33, 9 August 2013 (UTC)
Nice write up, I'll make sure to check it over carefully on the next big update. I had reason to run a small update this week and spotted some changes which I corrected for on the fly. By the way, the most recently added files have extra goodness added as comments embedded within the ogg file header, so context (which includes a link back to xeno-canto) should never be completely lost, even if a downloader forgets they originally grabbed an audio file from Commons. -- (talk) 14:53, 9 August 2013 (UTC)
Sounds great. Nice work. Jnthnjng (talk) 16:27, 9 August 2013 (UTC)



(per email) Recordings with subspecies seem to be getting assigned to invalid categories. For instance File:Vireo gilvus gilvus - Warbling_Vireo - XC102969.ogg is assigned to Category:Vireo gilvus gilvus rather than just Category:Vireo gilvus.

If the scientific name has two components; no problem. If it has three, then there's a subspecies. The appropriate logic would be:

If three parts in Sci name; check for subspecies category
If subspecies category exists, use it
else sue species category.

If there are only a few examples, I'm happy to mop up manually. Andy Mabbett (talk) 18:24, 17 January 2013 (UTC)

I think there are only a few examples. As the duff categories can easily be mass changed using hotcat, I suggest that's the way to go. If at a future time there are a few hundred more files to upload from xeno-canto, then I'll think about tweaking the category logic. Checking if a category exists and reacting accordingly is the sort of thing it might be worth fiddling around with for 10k+ files but not 1k-.
The other issue of file encoding problems I might address by comparing file play lengths on XC and WC, but still have to try out the WC API to see how easy that is. -- (talk) 19:08, 17 January 2013 (UTC)
✓ Done The WC API is rather useful for audio files - there's a heap of data there not presented on the audio page. A good tip for future projects I think. Comparing audio file lengths was therefore not too tricky, only minor wizardry needed. -- (talk) 23:59, 17 January 2013 (UTC)

Source code[edit]

Refer to