EmbedVideo
EmbedVideo |
- Системные требования:
- MediaWiki
- Разработчик:
- Jim R. Wilson, Mithgol the Webmaster, Александр Машин
- Текущая версия:
- 0.1.4
- Статус:
- бета-версия
EmbedVideo — расширение MediaWiki, создающее новую функцию парсера ({{ev:}}
), позволяющую внедрять видеоролики на вики-страницы.
Создатели
Первоначальный создатель — Jim R. Wilson (см. описание расширения на сайте MediaWiki и на странице создателя).
Mithgol the Webmaster, участник Традиции, доработал код расширения, чтобы оно могло невозбранно использоваться и для вставки звукозаписей, и для вставки фотопанорам, и для вставки слайдов, и для вставки таких видеопроигрывателей, ширина которых не относится к высоте в пропорции 425 / 350. Кроме того, добавлена возможность перехода проигрывателей в режим полноэкранного просмотра.
Использование
Помимо «Традиции», для которой это расширение было разработано, и где оно долго использовалось, пока не было заменено Embed, оно используется в «Викиреальности»,[1] «Циклопедии»[2] и Lurkmore.[3]
Исходный код
EmbedVideo.php
<?php
/*
* EmbedVideo.php - Adds a parser function embedding video and audio from popular sources.
* @author Mithgol the Webmaster, based on the work by Jim R. Wilson and contributions of Alex Mashin
* @version 0.1.4
* @copyright (C) 2007 Jim R. Wilson, (C) 2008-2010 Mithgol the Webmaster, (C) 2010, 2012 Alex Mashin
* @license The MIT License - http://www.opensource.org/licenses/mit-license.php
* ------------------------------------------------------------------------------------------------------
* Description:
* This is a MediaWiki extension which adds a parser function for embedding
* video and audio from popular sources (configurable).
* Requirements:
* MediaWiki 1.6.x, 1.9.x, 1.10.x or higher
* PHP 4.x, 5.x or higher.
* Installation:
* 1. Drop this script (EmbedVideo.php) in $IP/extensions
* Note: $IP is your MediaWiki install dir.
* 2. Enable the extension by adding this line to your LocalSettings.php:
* require_once('extensions/EmbedVideo.php');
* Version Notes:
* version 0.1.4.Pogrebnoj:
* Added rpod.ru.
* version 0.1.3:
* Updated Vesti's movie URL; deprecated wfLoadExtensionMessages () call removed.
* version 0.1.2.Mashin.28:
* Enabled VKontakte video in Mozilla.
* version 0.1.2.Mashin.27:
* Added VKontakte video.
* version 0.1.2.Mashin.26:
* Removed a fatal error under MW 1.17 (lines 163-164).
* version 0.1.2.Mithgol.25:
* Added &modestbranding=1 to both of YouTube codes;
* see http://habrahabr.ru/blogs/youtube/121188/ for details.
* YouTube player is 480×390 (normal) or 640×390 (wide) by default, as YouTube code suggests now,
* and its controls_height is 30, because version=3 is appended;
* see http://code.google.com/apis/youtube/player_parameters.html for details.
* version 0.1.2.Mashin.24:
* Added ustream.tv.
* version 0.1.2.Mithgol.23:
* Cosmetic fixes of version 0.1.2.Mashin.23.
* version 0.1.2.Mashin.23:
* Added support for MediaWiki 1.16 (changed message caching).
* version 0.1.2.Mithgol.22:
* Added support for NewsTube.Ru video.
* version 0.1.2.Mithgol.21:
* YouTube player is 480×385 (normal) or 640×385 (wide) by default, as YouTube code suggests now.
* version 0.1.2.Mithgol.20:
* Added support for http://vimeo.com/ video.
* version 0.1.2.Mithgol.19:
* Added yet another Muzicons audio player from http://muzicons.com/
* in order to play MP3 files uploaded to Traditio.
* version 0.1.2.Mithgol.18:
* Added support for http://www.slideshare.net/ documents and presentations.
* Added support for http://www.divshare.com/ audio.
* version 0.1.2.Mithgol.17:
* Added support for http://blip.tv/ video.
* version 0.1.2.Mithgol.16:
* Added support for http://www.vesti.ru/ news video.
* version 0.1.2.Mithgol.15:
* Added support for http://www.1tv.ru/ news video.
* version 0.1.2.Mithgol.14:
* Set correct controls_height for Video.Mail.Ru.
* version 0.1.2.Mithgol.13:
* Enabled support for Video.Mail.Ru.
* version 0.1.2.Mithgol.12:
* Bugfixes, coding style fixes, security fixes.
* version 0.1.2.Mithgol.11:
* Bugfixes for Gigapan and the description.
* version 0.1.2.Mithgol.10:
* Values of ['id_pattern'] and $idpattern now contain positive filters, not negative.
* Added a photo panorama provider (Gigapan), see http://gigapan.org/ for details.
* version 0.1.2.Mithgol.9:
* Added fullscreen abilities to OBJECT parameters and EMBED attributes.
* version 0.1.2.Mithgol.8:
* Added yet another kind of YouTube player: the wide one, for HD video (480×295 player, 16:9 video).
* version 0.1.2.Mithgol.7:
* Reflected the new YouTube player height (425×344 player, 4:3 video).
* version 0.1.2.Mithgol.6:
* BUGFIX: the site http://muzicons.com/ offers a bogus BB-code with 135x30 player,
* but actual dimesions is 150×50 (see their HTML code).
* version 0.1.2.Mithgol.5:
* Added Muzicons audio player from http://muzicons.com/
* version 0.1.2.Mithgol.4:
* Reflected the new RuTube player width (470 instead of former 400).
*
* Reflected the new imeem player dimensions (300×340 playlists, 300×110 audio tracks).
*
* Some players (like Google Video and YouTube) have constant height of video controls,
* and thus (width / (height - controlsHeight)) should be used instead of (width / height)
* when calculating the aspect ratio of the video.
*
* Added yet another audio content provider: Box.net/lite
*
* SECURITY NOTE: as http://tinyurl.com/5jpu3s says, the default value of AllowScriptAccess
* is 'sameDomain', so the remote Flash objects cannot communicate with our Tradtio pages,
* steal cookies, etc.; thus we are safe to add _any_ external Flash content providers.
* version 0.1.2.Mithgol.3:
* Now plays imeem audio with «-» or «_» in code.
* version 0.1.2.Mithgol.2:
* Fixed YouTube videos (they now require &rel=1).
* version 0.1.2.Mithgol.1:
* Bug fix: does not require width / height to be 425 / 350.
* (Now supports imeem.com audio, and YouTube does not glitch.)
* List of services is altered accommodating to the new requirements
* and general popularity of services across Traditio.Ru
* version 0.1.2:
* Bug fix: now can be inserted in lists without breakage (from newlines)
* Code cleanup: would previously give 'Notice' messages in PHP strict.
* version 0.1.1:
* Code cleanup: no functional difference.
* version 0.1:
* Initial release.
* -----------------------------------------------------------------------
* Copyright (c) 2007 Jim R. Wilson
* Copyright (c) 2008-2010 Mithgol the Webmaster
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
* -----------------------------------------------------------------------
*/
// Confirm MW environment
if (defined('MEDIAWIKI')) {
// Credits
$wgExtensionCredits['parserhook'][] = array(
'name'=>'EmbedVideo',
'author'=>'Mithgol the Webmaster (based on the work by Jim R. Wilson and contributions of Alex Mashin)',
'url'=>'http://traditio.ru/wiki/EmbedVideo',
'description'=>'Adds a parser function embedding video and audio and panoramas from popular sources.',
'version'=>'0.1.4'
);
// Messages:
$wgExtensionMessagesFiles ['embedvideo'] = dirname(__FILE__) . '/' . 'EmbedVideo.i18n.php';
/**
* Wrapper class for encapsulating EmbedVideo related parser methods
*/
class EmbedVideo {
protected static $initialized = false;
/**
* Sets up parser functions.
*/
function setup( ) {
// Setup parser hook
global $wgParser, $wgVersion;
$hook = (version_compare($wgVersion, '1.7', '<')?'#ev':'ev');
$wgParser->setFunctionHook( $hook, array($this, 'parserFunction') );
// Add system messages:
// Commented out on September 24th, 2012 by Alexander Mashin as wfLoadExtensionMessages () is now deprecated and messages get loaded anyway:
/*
if (!EmbedVideo::$initialized) {
wfLoadExtensionMessages ('embedvideo');
// Commented out on June 25th, 2011 by Alexander Mashin as this caused a fatal error under MW 1.17:
// $wgParser->disableCache();
EmbedVideo::$initialized = true;
}
*/
}
/**
* Adds magic words for parser functions.
* @param Array $magicWords
* @param String $langCode
* @return Boolean Always true
*/
function parserFunctionMagic( &$magicWords, $langCode='en' ) {
$magicWords['ev'] = array( 0, 'ev' );
return true;
}
/**
* Embeds video of the chosen service
* @param Parser $parser Instance of running Parser.
* @param String $service Which online service has the video.
* @param String $id Identifier of the chosen service
* @param String $width Width of video (optional)
* @param String $height Height of video (optional)
* @param String $param4 Additional parametre (optional)
* @param String $param5 Additional parametre (optional)
* @return String Encoded representation of input params (to be processed later)
*/
function parserFunction( $parser, $service=null, $id=null, $width=null, $height=null, $param4 = null, $param5 = null ) {
if ($service===null || $id===null) return '<div class="errorbox">'.wfMsg('embedvideo-missing-params').'</div>';
$params = array(
'service' => trim($service),
'id' => trim($id),
'width' => ($width===null?null:trim($width)),
'height' => ($height===null?null:trim($height))
);
global $wgEmbedVideoMinWidth, $wgEmbedVideoMaxWidth;
if (!is_numeric($wgEmbedVideoMinWidth) || $wgEmbedVideoMinWidth<100) $wgEmbedVideoMinWidth = 100;
if (!is_numeric($wgEmbedVideoMaxWidth) || $wgEmbedVideoMaxWidth>2048) $wgEmbedVideoMaxWidth = 2048;
global $wgEmbedVideoMinHeight, $wgEmbedVideoMaxHeight;
if (!is_numeric($wgEmbedVideoMinHeight) || $wgEmbedVideoMinHeight<10) $wgEmbedVideoMinHeight = 10;
if (!is_numeric($wgEmbedVideoMaxHeight) || $wgEmbedVideoMaxHeight>2048) $wgEmbedVideoMaxHeight = 2048;
global $wgEmbedVideoServiceList;
$service = $wgEmbedVideoServiceList[$params['service']];
if (!$service) return '<div class="errorbox">'.wfMsg('embedvideo-unrecognized-service',
@htmlspecialchars($params['service'])).'</div>';
$idpattern = ( isset($service['id_pattern']) ? $service['id_pattern'] : '%^[A-Za-z0-9_\\-]+$%' );
if ($id==null || !preg_match($idpattern, $id)) {
$id = htmlspecialchars($params['id']);
return '<div class="errorbox">'.wfMsgForContent('embedvideo-bad-id', $id,
@htmlspecialchars($params['service'])).'</div>';
}
$id = htmlspecialchars($params['id']);
$defaultWidth = ( isset($service['default_width']) ? $service['default_width'] : 425 );
$defaultHeight = ( isset($service['default_height']) ? $service['default_height'] : 350 );
$controlsHeight = ( isset($service['controls_height']) ? $service['controls_height'] : 0 );
// Build URL and output embedded flash object
$ratio = $defaultWidth / ($defaultHeight - $controlsHeight);
$width = $defaultWidth;
if ($params['width']!==null) {
// Check whether $params['width'] is invalid:
if (!is_numeric($params['width']) ||
$params['width'] < $wgEmbedVideoMinWidth ||
$params['width'] > $wgEmbedVideoMaxWidth
) return
'<div class="errorbox">'.
wfMsgForContent('embedvideo-illegal-width',
@htmlspecialchars($params['width'])
).'</div>';
$width = $params['width'];
}
$height = round($width / $ratio) + $controlsHeight;
if ($params['height']!==null) {
// Check whether $params['height'] is invalid:
if (!is_numeric($params['height']) ||
$params['height'] < $wgEmbedVideoMinHeight ||
$params['height'] > $wgEmbedVideoMaxHeight
) return
'<div class="errorbox">'.
wfMsgForContent('embedvideo-illegal-height',
@htmlspecialchars($params['height'])
).'</div>';
$height = $params['height'];
}
$url = wfMsgReplaceArgs($service['url'], array($id, $width, $height, $param4, $param5));
return $parser->insertStripItem (
wfMsgForContent (
// VKontakte video does not load when an embed tag is present:
$service ['noembed'] ? 'embedvideo-object-clause' : 'embedvideo-embed-clause'
, $url, $width, $height
)
, $parser->mStripState
);
}
}
/**
* Wrapper function for language magic call (hack for 1.6)
*/
// Create global instance and wire it up!
$wgEmbedVideo = new EmbedVideo();
$wgExtensionFunctions[] = array($wgEmbedVideo, 'setup');
if (version_compare($wgVersion, '1.7', '<')) {
# Hack solution to resolve 1.6 array parameter nullification for hook args
function wfEmbedVideoLanguageGetMagic( &$magicWords ) {
global $wgEmbedVideo;
$wgEmbedVideo->parserFunctionMagic( $magicWords );
return true;
}
$wgHooks['LanguageGetMagic'][] = 'wfEmbedVideoLanguageGetMagic';
} else {
$wgHooks['LanguageGetMagic'][] = array($wgEmbedVideo, 'parserFunctionMagic');
}
/*
* Now starting the list of services.
*
* It may be altered via LocalSettings.php file,
* see examples at http://jimbojw.com/wiki/index.php?title=EmbedVideo_Extension#Configuration
*
* Only services used in Traditio (www.traditio.ru) are listed here,
* see also the original list at http://jimbojw.com/wiki/index.php?title=EmbedVideo
*/
$wgEmbedVideoServiceList = array(
'googlevideo' => array(
'id_pattern' => '%^[0-9-]+$%',
'url' => 'http://video.google.com/googleplayer.swf?docId=$1&fs=true',
'default_width' => 400,
'default_height' => 326,
'controls_height' => 27
),
'youtube' => array(
'url' => 'http://www.youtube.com/v/$1?version=3&fs=1&modestbranding=1',
'default_width' => 480,
'default_height' => 390,
'controls_height' => 30
),
'youtubewide' => array(
'url' => 'http://www.youtube.com/v/$1?version=3&fs=1&modestbranding=1',
'default_width' => 640,
'default_height' => 390,
'controls_height' => 30
),
'rutube' => array(
'id_pattern' => '%^[a-z0-9]+$%',
'url' => 'http://video.rutube.ru/$1',
'default_width' => 470,
'default_height' => 353
),
'imeemtrack' => array(
'url' => 'http://media.imeem.com/m/$1/aus=false/',
'default_width' => 300,
'default_height' => 110
),
'imeemsequence' => array(
'url' => 'http://media.imeem.com/pl/$1/aus=false/',
'default_width' => 300,
'default_height' => 340
),
'imeemshuffle' => array(
'url' => 'http://media.imeem.com/pl/$1/aus=false/autoShuffle=true/',
'default_width' => 300,
'default_height' => 340
),
'box' => array(
'url' => 'http://www.box.net/mp3player/player.swf?playlistURL=http://www.box.net/lite/playlist/$1',
'default_width' => 310,
'default_height' => 65
),
'muzicons' => array(
'url' => 'http://muzicons.com/musicon3.swf?&nomuz=muzicon%20unavailable&site=http://muzicons.com/&icon_pic=12.png&music_file=$1&bg_color=000000&type_of_clip=whith_bar&text_color=FFFFFF&text_message=listening',
'default_width' => 150,
'default_height' => 50
),
'tradicons' => array(
'id_pattern' => '%^[01-9a-zA-Z]{1}/[01-9a-zA-Z]{2}/[01-9a-zA-Z_.-]+\.[Mm][Pp]3$%',
'url' => 'http://muzicons.com/musicon_v_srv_new.swf?&nomuz=muzicon%20unavailable&site=http://muzicons.com/&icon_pic=12.png&music_file=http://traditio.ru/images/$1&bg_color=000000&type_of_clip=whith_bar&text_color=FFFFFF',
'default_width' => 150,
'default_height' => 50
),
'gigapan' => array(
'id_pattern' => '%^[0-9]+/tiles/(&width=[0-9]+&height=[0-9]+&nlevels=[0-9]+&cright=[0-9]+\\.0&cbottom=[0-9]+\\.0)?$%',
'url' => 'http://gigapan.org/viewer/PanoramaViewer.swf?url=http://share.gigapan.org/gigapans0/$1&suffix=.jpg&cleft=0&ctop=0',
'default_width' => 600,
'default_height' => 400
),
'videomailru' => array(
'id_pattern' => '%^[A-Za-z01-9_-]+/[A-Za-z01-9_-]+/\\$[01-9]+\\$[01-9]+\\$[01-9]+&page=[01-9]+&imaginehost=video\\.mail\\.ru&perlhost=video\\.mail\\.ru&alias=mail&username=[A-Za-z01-9_-]+&albumid=[A-Za-z01-9_-]+&id=[01-9]+&catalogurl=http://video\\.mail\\.ru/themes/[A-Za-z01-9_-]+$%',
'url' => 'http://img.mail.ru/r/video2/player_v2.swf?par=http://content.video.mail.ru/mail/$1',
'default_width' => 450,
'default_height' => 375,
'controls_height' => 36
),
'1tv' => array(
'id_pattern' => '%^[01-9]+$%',
'url' => 'http://www.1tv.ru/nvideo/$1',
'default_width' => 322,
'default_height' => 288
),
'vesti' => array(
'id_pattern' => '%^[01-9]+$%',
'url' => 'http://www.vesti.ru/i/flvplayer_videoHost.swf?vid=$1&fbv=true&isHome=false',
'default_width' => 320,
'default_height' => 295
),
'blip' => array(
'id_pattern' => '/^[A-Za-z0-9_%\\-]+$/',
'url' => 'http://blip.tv/play/$1',
'default_width' => 480,
'default_height' => 390,
'controls_height' => 30
),
'slideshare' => array(
'id_pattern' => '/^[a-z01-9-]+&stripped_title=[a-z01-9-]+$/',
'url' => 'http://static.slidesharecdn.com/swf/ssplayer2.swf?rel=0&doc=$1',
'default_width' => 425,
'default_height' => 355,
'controls_height' => 37
),
'divshareaudio' => array(
'id_pattern' => '/^[01-9a-z-]+$/',
'url' => 'http://www.divshare.com/flash/playlist?myId=$1',
'default_width' => 335,
'default_height' => 28
),
'vimeo' => array(
'id_pattern' => '/^[01-9]+$/',
'url' => 'http://vimeo.com/moogaloop.swf?clip_id=$1&server=vimeo.com&show_title=1&show_byline=0&show_portrait=0&color=&fullscreen=1',
'default_width' => 400,
'default_height' => 300
),
'newstube' => array(
'id_pattern' => '/^[01-9a-f-]+$/',
'url' => 'http://www.newstube.ru/FreshPlayer.swf?guid=$1&placement=embed',
'default_width' => 400,
'default_height' => 300
),
'ustream' => array(
'id_pattern' => '/^[01-9a-f-]+$/',
'url' => 'http://www.ustream.tv/flash/viewer.swf?cid=$1',
'default_width' => 360,
'default_height' => 226
),
'vkontakte' => array(
'id_pattern' => '/^-?[01-9]+$/',
'url' => 'http://vkontakte.ru/video_ext.php?oid=$1&id=$4&hash=$5&hd=1',
'default_width' => 304,
'default_height' => 180,
'noembed' => true
),
'rpod' => array(
'id_pattern' => '/^\d+$/',
'url' => 'http://s.rpod.ru/swf/playa.swf?xmlURL=http%3A%2F%2Fs.rpod.ru%2Fxml%2Faudio_waveform%2Fa$1.xml',
'default_width' => 300,
'default_height' => 110
)
);
} // End MW Environment wrapper
?>
EmbedVideo.i18n.php
<?php
$messages = array();
$messages ['en'] = array (
'embedvideo-missing-params' => 'EmbedVideo is missing a required parameter.'
, 'embedvideo-bad-params' => 'EmbedVideo received a bad parameter.'
, 'embedvideo-unparsable-param-string' => 'EmbedVideo received the unparsable parameter string "<tt>$1</tt>".'
, 'embedvideo-unrecognized-service' => 'EmbedVideo does not recognize the video service "<tt>$1</tt>".'
, 'embedvideo-bad-id' => 'EmbedVideo received the bad id "$1" for the service "$2".'
, 'embedvideo-illegal-width' => 'EmbedVideo received the illegal width parameter "$1".'
, 'embedvideo-illegal-height' => 'EmbedVideo received the illegal height parameter "$1".'
, 'embedvideo-embed-clause' =>
'<object width="$2" height="$3">'
. '<param name="movie" value="$1"></param>'
. '<param name="wmode" value="transparent"></param>'
. '<param name="allowFullScreen" value="true"></param>'
. '<embed src="$1" type="application/x-shockwave-flash" '
. 'wmode="transparent" allowFullScreen="true" width="$2" height="$3">'
. '</embed></object>'
, 'embedvideo-object-clause' =>
'<object width="$2" height="$3" data="$1">'
. '<param name="movie" value="$1"></param>'
. '<param name="wmode" value="transparent"></param>'
. '<param name="allowFullScreen" value="true"></param>'
. '</object>'
);
$messages ['ru'] = array (
'embedvideo-missing-params' => 'EmbedVideo не нашло необходимого параметра.'
, 'embedvideo-bad-params' => 'EmbedVideo получило неверный параметр.'
, 'embedvideo-unparsable-param-string' => 'EmbedVideo не может разобрать параметр. "<tt>$1</tt>".'
, 'embedvideo-unrecognized-service' => 'EmbedVideo не знает указанной видеослужбы. "<tt>$1</tt>".'
, 'embedvideo-bad-id' => 'EmbedVideo получило неверный id "$1" for the service "$2".'
, 'embedvideo-illegal-width' => 'EmbedVideo получило неверную ширину "$1".'
, 'embedvideo-illegal-height' => 'EmbedVideo получило неверную высоту "$1".'
, 'embedvideo-embed-clause' => $messages ['en'] ['embedvideo-embed-clause']
, 'embedvideo-object-clause' => $messages ['en'] ['embedvideo-object-clause']
);
?>
Применение расширения
Вызов расширения EmbedVideo применялось в Традиции не непосредственно, а в составе нескольких шаблонов, каждый из которых предназначен для вставки мультимедийных данных с некоторого сайта (по шаблону на сайт).
Примечания
Вставка мультимедийных файлов в Традицию | |
---|---|
Для вставки видеозаписей |
• все ролики (кроме 1tv) {{RuTube}} • {{1tv}} • {{Вести}} • {{NewsTube}} • {{VideoMailRu}} • {{BlipTV}} • {{YouTube}} • {{Google Video}}† • {{Vimeo}} • {{VKontakte}} • {{RuTV}} • {{Telegram}} |
Для вставки видеотрансляций | {{ustream}} |
Для вставки подкастов | {{rpod}} |
Для вставки звукозаписей | {{listen}} • {{audio}} • {{сказать}} • {{звук}} • {{mp3}} • {{BoxNetLite}} • {{imeem}}† • {{divshareaudio}} • {{soundcloud}} |
Для вставки нот |
<score> |
Для вставки фотопанорам | {{Gigapan}} |
Для вставки слайдов | {{SlideShare}} |
Функция парсера |
{{#embed:}} (используется сейчас), {{#ev:}} (использовалось ранее) |
Настройки | Сообщения MediaWiki |
Необходимые расширения | EmbedVideo (использовалось «Традицией» ранее) или Embed (используется сейчас) • Score • MwEmbedSupport • TimedMediaHandler |
∘ ∘ ∘ |