- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试对 Canvas 的帧进行计时,以便与后台播放的音频同步。
当我使用 window.requestAnimationFrame 时,您会在不同的浏览器/计算机上在一秒钟内获得不稳定的帧数。我还尝试了 setInterval(function(){//code }, 1);
,它比 window.requestAnimationFrame
更接近完美,但它仍然没有完成工作正确。
setInterval
每毫秒触发一次,然后检查应在 x 时间生成哪些对象,并且它还会清除并更新 Canvas 。另外,我使用毫秒来计算对象的速度,以便它们在正确的 x 时间到达 Canvas 上的位置。
有更好的方法吗?
我将在下面列出我的代码,以及我当前的 CodePen 的链接,以便您可以看到它的运行情况。 (点击 Canvas 区域即可开始动画背景中有音乐需要同步,但只有点击才会开始)
var Queues = [
[1, '#FFFFFF', 'line', true, [20,20], [80,80], 500, 950],
[2, '#FFFFFF', 'line', true, [80,80], [55,20], 950, 1200]
];
var playing = false;
$(document).click(function(){
if(playing == false) {
var audio = document.getElementById("audio");
audio.currentTime = 0;
audio.play();
apparatus();
playing = true;
} else {
var audio = document.getElementById("audio");
audio.pause();
playing = false;
$('body canvas').remove();
}
});
function apparatus() {
var canvas, context, toggle, time = 0, vidtime = 0;
var points = [];
init();
function init() {
canvas = document.createElement( 'canvas' );
context = canvas.getContext( '2d' );
canvas.width = $(document).width();
canvas.height = $(document).height();
document.body.appendChild( canvas );
}
var point = function(options) {
this.position = {}, this.end_position = {}, this.distance = {}, this.velocity = {}, this.time = {};
points.push(this);
// TIMING
this.time.start = options[6];
this.time.end = options[7];
// VECTORS
this.position.x = options[4][0] * (canvas.width / 100);
this.position.y = options[4][1] * (canvas.height / 100);
this.end_position.x = options[5][0] * (canvas.width / 100);
this.end_position.y = options[5][1] * (canvas.height / 100);
this.distance.x = Math.abs(this.position.x - this.end_position.x);
this.distance.y = Math.abs(this.position.y - this.end_position.y);
if(this.position.x > this.end_position.x) {
this.velocity.x = -Math.abs(this.distance.x / (this.time.end - this.time.start));
} else {
this.velocity.x = Math.abs(this.distance.x / (this.time.end - this.time.start));
}
if(this.position.y > this.end_position.y) {
this.velocity.y = -Math.abs(this.distance.y / (this.time.end - this.time.start));
} else {
this.velocity.y = Math.abs(this.distance.y / (this.time.end - this.time.start));
}
// STYLING
this.style = options[2];
this.color = options[1];
//-- STYLING / STYLE TYPES
if(this.style == 'line') {
}
}
point.prototype.draw = function() {
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
context.fillStyle = this.color;
context.beginPath();
context.arc( this.position.x, this.position.y, 10, 0, Math.PI * 2, true );
context.closePath();
context.fill();
}
setInterval(function(){
time++;
console.log(time);
context.fillStyle = '#000000';
context.fillRect(0, 0, $(document).width(), $(document).height());
for(var i = 0; i < Queues.length; i++) {
if(time == Queues[i][6]) {
new point(Queues[i]);
}
if(time == Queues[i][7]) {
console.log('la');
}
}
for(var i = 0; i <= points.length; i++) {
if(points[i] != null) {
points[i].draw();
}
}
}, 1);
}
最佳答案
正在同步
您不能依赖 setInterval 或 setTimeout,因为它们只会尽可能接近请求的时间进行响应,因此对于同步动画和时间等内容非常不可靠。
您需要使用一致的时间进行同步。您还必须使您的代码适应迟到。
日期和 requestAnimationFrame
首先要抓紧时间。 JavaScript 通过 Date 对象提供以毫秒为单位的时间。
以下内容将返回自过去某个时间以来的当前时间(以毫秒为单位)(我不知道 1452798031458 毫秒前的时间)
var currentTime = new Date().valueOf();
或者,如果您使用 window.requestAnimationFrame,您将获得时间作为第一个参数
// main update loop
function update(time){
// time is the millisecond time
requestAnimationFrame(update); // request new frame
}
update(new Date().valueOf);
如果您希望某件事在设定的时间发生,您必须考虑测试时间的机会之间的时间,因为这可能会有所不同。
定期事件时间
让我们尝试一个基于帧时间的计时事件。
首先使用一些变量来跟踪时间
var frameTime; // time between calls to update
var lastFrameTime; // the time of the perviouse call to update
var eventTime; // the event start time that we want to stay in sync with
var timeInterval = 1000; // when we want sync events
然后开始我们想要保持同步的事件。
function startSound(){
sound.play(); // assuming you have the sound.
eventTime = new Date().valueOf(); // now
}
更新函数将在尽可能接近我们想要的时间的情况下执行正确的操作。
function update(time){
frameTime = time - lastFrameTime; // how long since the last call to update
var timeSinceEvent = time-eventTime; // get the time since the event started
var timeSinceLastSync = timeSinceEvent % timeInterval;
// Several options here so explained below
requestAnimationFrame(update); // request new frame
lastFrameTime = time; // remember the last frame time
}
startSound(); // start playing
lastFrameTime = new Date().valueOf;
update(new Date().valueOf);
现在你有一些选择。人类的感知不太擅长在 1/10 秒以下的任何时间分离视觉效果,人类的听觉非常擅长及时分离事件(当在录音中弹奏吉他时出现 10 毫秒的延迟时,我会感到恼火),所以你有考虑您要展示的内容。
视觉事件
视觉上是最简单的。您只需在同步时间之后尽可能接近地触发 snyc 事件即可。
if(timeSinceLastSync > timeInterval){
// do the visual event
eventTime += timeInterval; // update the event time to the time this
// event was to have happened.
}
这将在帧时间 1/60(分钟)秒内触发视觉事件。您会注意到我添加到了 eventTime。我没有得到当前时间,因为当前时间可能会相差 30 毫秒,如果我们添加哪怕一个毫秒的误差,它也会很快累积。
音频、高精度事件
对于音频事件,我们通过查看最后一帧时间来抢占事件时间
// make sure we are near the next event time. this is to avoid firing the event
// twice. Once on the frame before and once on the frame after.
if((timeInterval - timeSinceLastSync) > timeInterval/2){
// will the time to the new sync event be less than half the last frame time
// or have we passed that time.
if((timeInterval - timeSinceLastSync) < frameTime || timeSinceLastSync > timeInterval ){
// fire the synced event.
eventTime += timeInterval; // update the event time to the time this
// event was or will happened.
}
}
我们在这里所做的是使用最后一帧完成所需的时间,并假设当前帧将花费相同的时间。然后,我们找到距离同步事件还有多长时间,如果该时间小于帧时间的一半,则触发该事件。或者我们可能已经过了同步事件时间。无论哪种方式,我们现在都需要触发该事件。
然后再次通过添加来更新当前同步事件时间。
此方法将使您尽可能接近您想要触发事件的时间。 (假设 60fps,则在 1/120 秒内)
改进
您可以对此进行改进。 JavaScript 是阻塞的,所以有些事情你需要等到更新函数结束。您还可以通过获取退出功能之前的时间来跟踪您在更新功能中花费的时间。然后,您将估计您请求触发的代码需要多长时间才会发生,并且可以将其包含在计算中。通常,帧之间的时间为 16 毫秒,但您的更新函数可能只运行 8 毫秒,因此会触发事件下一帧之前 8 毫秒。
性能和微秒
某些浏览器上还有一个微秒(1/1,000,000 秒)计时器,称为性能
// assume no performance API
var usePerformance = false
// at the start of you code check if its available
if(typeof performance === "function"){ // is performance available
usePerformance = true;
}
为了避免每次需要时都必须测试性能 API,请使用任一 API 创建单独的函数
var updateP = function(){
}
// normal update function
var updateN = function(){
}
// set the correct update function
var update;
if(usePerformance){
update = updateP;
}else{
update = updateN;
}
使用性能
使用性能 API
var now = performance.now(); // returns the time in ms with a fractional
// representing the microseconds.
事件之间的时间
var n = performance.now();
console.log(performance.now()-n); // returns 0.021 depending on the system speed
希望这有帮助。
关于javascript - 同步音频和 Canvas ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34797036/
我一直在为实时流和静态文件(HTTP 上的 MP3)构建网络广播播放器。我选了Howler.js作为规范化 quirks 的后端的 HTML5 Audio (思考:自动播放、淡入/淡出、进度事件)。
vue移动端input上传视频、音频,供大家参考,具体内容如下 html部分 ?
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 7年前关闭。 Improve this questi
我想在我的程序中访问音频和视频。 MAC里面可以吗? 我们的程序在 Windows 上运行,我使用 directshow 进行音频/视频编程。但我想在 MAC 中开发相同的东西。 有没有像direct
我的应用程序(使用 Flutter 制作,但这应该无关紧要)具有类似于计时器的功能,可以定期(10 秒到 3 分钟)发出滴答声。我在我的 Info.plist 中激活了背景模式 Audio、AirPl
我是 ionic 2 的初学者 我使用了音频文件。 import { Component } from '@angular/core'; import {NavController, Alert
我有一个包含ListView和图片的数据库,我想在每个语音数据中包含它们。我已经尝试过,但是有很多错误。以下是我的java和xml。 数据库.java package com.example.data
我在zend framework 2上建立了一个音乐社交网络。您可以想象它与SoundCloud相同,用户上传歌曲,其他用户播放它们,这些是网站上的基本操作。 我知道将要托管该页面的服务器将需要大量带
我正在尝试在android应用中播放音频,但是在代码中AssetFileDescriptor asset1及其下一行存在错误。这是代码: MediaPlayer mp; @Override prote
我对 WordPress Audio Shortcode有问题。我这样使用它: 但是在前面,在HTML代码中我得到了: document.createElement('audio');
我正在做一项关于降低噪音的滤波技术的实验。我在数据集中的样本是音频文件(.wav),因此,我有:原始录制的音频文件,我将它们与噪声混合,因此变得混合(噪声信号),我将这些噪声信号通过滤波算法传递,输出
一个人会使用哪种类型的神经网络架构将声音映射到其他声音?神经网络擅长学习从序列到其他序列,因此声音增强/生成似乎是它们的一种非常流行的应用(但不幸的是,事实并非如此-我只能找到一个(相当古老的)洋红色
这个让我抓狂: 在专用于此声音播放/录制应用程序的 Vista+ 计算机上,我需要我的应用程序确保(默认)麦克风电平被推到最大。我该怎么做? 我找到了 Core Audio lib ,找到了如何将 I
{ "manifest_version": 2, "name": "Kitten Radio Extension", "description": "Listen while browsi
class Main { WaveFileReader reader; short[] sample; Complex[] tmpComplexArray; publi
我正在使用电话录音软件(android),该软件可以记录2个人在电话中的通话。每个电话的输出是一个音频文件,其中包含来自 call 者和被 call 者的声音。 但是,大多数情况下,运行此软件的电话发
我正在构建一个需要语音激活命令的Web应用程序。我正在使用getUserMedia作为音频输入。 对于语音激活命令,该过程是用户将需要通过记录其语音来“校准”命令。例如,对于“停止”命令,用户将说出“
我正在开发一个Cordova应用程序,并将PouchDB用作数据库,当连接可用时,它将所有信息复制到CouchDB。 我成功存储了简单的文本和图像。 我一直在尝试存储视频和音频,但是没有运气。 我存储
我正在开发web application,我必须在其中使用.MP3的地方使用播放声音,但是会发生问题。 声音为play good in chrome, Firefox,但为safari its not
如何减少音频文件的位深?是否忽略了MSB或LSB?两者混合吗? (旁问:这叫什么?) 最佳答案 TL / DR:将音频曲线高度变量右移至较低位深度 可以将音频视为幅度(Y轴)随时间(X轴)的模拟曲线。
我是一名优秀的程序员,十分优秀!