Есть страница, на ней плееры (Flash) из сервиса Uppod, но не во всех браузерах они
проявляются, а главное их не видно в мобильных устройствах.
Решил заменить их на HTML5 audio, но не могу найти решение непрерывного, последовательного
воспроизведения, когда после завершения проигрывания одного плеера начинает звучать
следующий, к примеру, или тут.
Есть варианты плееров с плейлистами, но мне хотелось бы несколько плееров на странице,
между которыми будет текст.
var audio = document.getElementsByTagName("audio");
for (let i = 0; i < audio.length; i++) {
audio[i].addEventListener('ended', function() {
if (audio[i].duration === audio[i].currentTime) {
audio[i + 1].play();
}
});
}
Ответы
Ответ 1
Чтобы проигрывались несколько плееров подряд, за это отвечает событие ended.
Надо его отследить и все. Мне кажется данная конструкция на столько проста, что и
пояснять тут нечего
var audio = document.getElementsByTagName("audio");
for (let i = 0; i < audio.length; i++) {
audio[i].addEventListener('ended', function() {
if (audio[i].duration === audio[i].currentTime) {
audio[i + 1].play();
}
});
}
Ответ 2
Думаю нужно поработать с events. То есть запустить проигрывание на первом плеере,
затем когда произойдет событие 'ended' запускай второй плеер , и так далее. Например:
document.addEventListener("DOMContentLoaded", () => {
let allAudio = Array.from(document.getElementsByTagName('audio'));
allAudio[0].play();
allAudio.forEach((item, index) => {
item.addEventListener('ended', (ev) => {
if (index === allAudio.length - 1) {
index = 0
} else {
index++;
}
allAudio[index].play();
})
});
});
Пускай не самый лучший код, но думаю концепция понятна.
Для первоначального запуска первого плеера можно использовать уже, что душе угодно.
Ниже ссылка на видео , аудио события:
https://developer.mozilla.org/ru/docs/Web/Guide/Events/Media_events
Пример.
Вообще, интересует, как из аудиофайла получить рисунок волноформы, желательно нужного
размера, в графическом формате (png, jpg).
В аудиоредакторах, например Logic pro x волноформа отображается, но нет возможности
сохранить ее, как рисунок.
Скриншот не лучший вариант, т.к. при уменьшении/увеличении изображения, теряем в
качестве.
Ответы
Ответ 1
Технологии рисования звуковой волны делятся на два этапа - сначала из аудиофайла
получают данные для рисования. На JS это делают с помощью WebAudio Api - функции decodeAudioData().
Второй этап - вывод рисунка можно сделать очень по-разному. Пожалуй с помощью тега
canvas будет попроще, но если требуется сохранить изображение в определённом формате,
то есть другой способ - записать данные изображения в требуемом графическом формате
в массив типа blob. Из него их потом можно будет задать, как атрибут src для элемента
img, как буд-то из файла. А если это же самое задать, как атрибут href для ссылки,
то потом кликом по этой ссылке можно будет скачать изображение в папку для загрузок,
указанную в настройках браузера. Так же можно будет сохранить изображение, кликнув
правой клавишей по рисунку и выбрав сохранить изображение.
В этой теме: Получение сырых данных Audio в js во втором ответе есть пример кода
рисования звуковой волны с последующей возможностью сохранения рисунка пока что в формате BMP.
Ответ 2
Аудиоволна в цифровом виде это массив значений (целых, или с плавающей запятой),
отображающих силу сигнала в конкретный момент времени. Что бы нарисовать ее, мы делим
все сэмплы (длину массива) на количество пикселей, для которого будем рисовать картинку.
Совмещая участок массива с каждым пикселем, ищем максимальный и минимальный уровень
сигнала на данном участке времени, и рисуем соответствующую вертикальную линию.
По ссылке описано, как рисуется waveform в Audacity: https://manual.audacityteam.org/man/audacity_waveform.html
Они еще рисуют среднее квадратичное на каждом участке, что соответствует тому, как
громко в целом слышен данный участок.
Ниже примерный код на джаваскрипте, можно запустить прям отсюда, подсунув ему mp3
файл, и скачав картинку в png.
function processFile() {
var reader = new FileReader();
reader.onload = function (e) {
let buffer = e.target.result;
let ctx = new AudioContext();
ctx.decodeAudioData(buffer).then(function (audioBuffer) {
// здесь массив Float32
// для примера рисуем только первый канал
let channel = audioBuffer.getChannelData(0);
var allMin = 0;
var allMax = 0;
for (var i = 0; i < channel.length; i++) {
allMin = channel[i] < allMin ? channel[i] : allMin;
allMax = channel[i] > allMax ? channel[i] : allMax;
}
let allAvg = (allMin + allMax) / 2;
let width = parseInt(document.querySelector('#width').value);
let height = parseInt(document.querySelector('#height').value);
let canvas = document.querySelector('#canvas');
canvas.width = width;
canvas.height = height;
let ctx = canvas.getContext('2d');
ctx.fillStyle = '#CCCCCC';
ctx.fillRect(0, 0, width, height);
for (var i = 0; i < width; i++) {
var min = 0;
var max = 0;
let sampleFrom = Math.floor(channel.length * i / width);
let sampleTo = Math.floor(channel.length * (i + 1) / width);
var rms = 0;
// считаем минимум и максимум на участке + среднее квадратичное
for (var j = sampleFrom; j < sampleTo; j++) {
min = channel[j] < min ? channel[j] : min;
max = channel[j] > max ? channel[j] : max;
rms += channel[j] * channel[j] / (sampleTo - sampleFrom);
}
var fromY = Math.floor(height * (allMax - min) / (allMax - allMin));
var toY = Math.floor(height * (allMax - max) / (allMax - allMin));
ctx.fillStyle = '#414BD3';
ctx.fillRect(i, fromY, 1, toY - fromY);
rms = Math.sqrt(rms);
var fromY = Math.floor(height / 2 + height * (allAvg - rms) / (allMax
- allMin));
var toY = Math.floor(height / 2 + height * (allAvg + rms) / (allMax
- allMin));
ctx.fillStyle = '#777CE3';
ctx.fillRect(i, fromY, 1, toY - fromY);
}
});
};
reader.readAsArrayBuffer(document.querySelector('#file').files[0]);
}
function downloadImage() {
let image = document.querySelector('#canvas').toDataURL('image/png').replace('image/png',
'image/octet-stream');
let a = document.querySelector('a');
a.setAttribute('download', 'image.png');
a.setAttribute('href', image);
}
Здравствуйте.
Нужно, чтобы при входящем сообщении на сайте проигрывался звук, по типу, как у контакта! Как это реализовать? Скрипт проверки на наличие сообщений имеется, как в него вставить воспроизведение звукового файла?
Решил проблему так:
function soundClick() {
var audio = new Audio(); // Создаём новый элемент Audio
audio.src = 'n.mp3'; // Указываем путь к звуку "клика"
audio.autoplay = true; // Автоматически запускаем
}
Ответ
Предлагаю не создавать объект Audio каждый раз, ведь вы можете создать его однажды и использовать повторно Ниже накиданный на скорую руку симулятор чата
function MessageClass(userName, text, avatarSrc, sendTime){
var self = this;
this.UserName = userName;
this.Text = text;
this.SendTime = sendTime.toLocaleTimeString();
this.AvatarSrc = avatarSrc;
}
var chat = new function (){
var audio = document.createElement('audio'),
source = document.createElement('source'),
tid = 0;
source.type = 'audio/mpeg';
source.src = 'http://dl.dropbox.com/u/1538714/article_resources/song.m4a';
audio.appendChild(source);
this.Messages = ko.observableArray([]);
this.Messages.subscribe(function (){
clearInterval(tid);
audio.pause();
audio.currentTime = 0;
audio.play();
// только потому что трек длинный
tid = setTimeout(function(){
audio.pause();
}, 400);
});
}
ko.applyBindings(chat, document.getElementById("chat"));
(function onMessage(){
chat.Messages.push(
new MessageClass(
faker.name.firstName() + ' ' + faker.name.lastName(),
faker.hacker.phrase(),
faker.image.avatar(),
new Date()
)
);
scrollTo(0, document.body.offsetHeight);
setTimeout(onMessage, faker.random.number(1500) + 500);
})(chat, faker);
fieldset{
position: relative;
}
fieldset:nth-child(2n){
margin-left:24px;
}
legend{
color:#0a0;
}
time{
position:absolute;
right:12px;
top:0px;
background:#FFF;
color: #a00;
display:inline-block;
padding: 0px 6px;
font-size: 12px;
}
img{
float:left;
width: 60px;
margin-right: 12px;
border-radius:30px;
height:60px;
}
А вот здесь вы и сами можете писать сообщения:
function MessageClass(userName, text, avatarSrc, sendTime){
var self = this;
this.UserName = userName;
this.Text = text;
this.SendTime = sendTime.toLocaleTimeString();
this.AvatarSrc = avatarSrc;
}
var chat = new function (){
var self = this,
tid = 0,
audio = document.createElement('audio'),
source = document.createElement('source'),
generateFakeMessage = function (){
self.Messages.push(
new MessageClass(
faker.name.firstName() + ' ' + faker.name.lastName(),
faker.hacker.phrase(),
faker.image.avatar(),
new Date()
)
);
scrollTo(0, document.body.offsetHeight);
};
source.type = 'audio/mpeg';
source.src = 'http://dl.dropbox.com/u/1538714/article_resources/song.m4a';
audio.appendChild(source);
self.Messages = ko.observableArray([]);
self.UserMessage = ko.observable('');
self.sendMessage = function(){
if (self.UserMessage()){
chat.Messages.push(new MessageClass(
'My account',
self.UserMessage(),
'//s3.amazonaws.com/uifaces/faces/twitter/psdesignuk/128.jpg',
new Date()
));
self.UserMessage('');
}
setTimeout(generateFakeMessage, 1000);
return false;
};
self.Messages.subscribe(function (){
clearInterval(tid);
audio.pause();
audio.currentTime = 1;
audio.play();
// только потому что трек длинный
tid = setTimeout(function(){
audio.pause();
}, 400);
});
generateFakeMessage();
}
ko.applyBindings(chat, document.getElementById("chat"));
fieldset{
position: relative;
}
fieldset:nth-child(2n){
margin-left:24px;
}
legend{
color:#0a0;
}
time{
position:absolute;
right:12px;
top:0px;
background:#FFF;
color: #a00;
display:inline-block;
padding: 0px 6px;
font-size: 12px;
}
img{
float:left;
width: 60px;
margin-right: 12px;
border-radius:30px;
height:60px;
}
input, button{
margin-top:6px;
width:100%;
}