
Recherche avancée
Médias (91)
-
Spoon - Revenge !
15 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
My Morning Jacket - One Big Holiday
15 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Zap Mama - Wadidyusay ?
15 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
David Byrne - My Fair Lady
15 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Beastie Boys - Now Get Busy
15 septembre 2011, par
Mis à jour : Septembre 2011
Langue : English
Type : Audio
-
Granite de l’Aber Ildut
9 septembre 2011, par
Mis à jour : Septembre 2011
Langue : français
Type : Texte
Autres articles (90)
-
MediaSPIP version 0.1 Beta
16 avril 2011, parMediaSPIP 0.1 beta est la première version de MediaSPIP décrétée comme "utilisable".
Le fichier zip ici présent contient uniquement les sources de MediaSPIP en version standalone.
Pour avoir une installation fonctionnelle, il est nécessaire d’installer manuellement l’ensemble des dépendances logicielles sur le serveur.
Si vous souhaitez utiliser cette archive pour une installation en mode ferme, il vous faudra également procéder à d’autres modifications (...) -
Amélioration de la version de base
13 septembre 2013Jolie sélection multiple
Le plugin Chosen permet d’améliorer l’ergonomie des champs de sélection multiple. Voir les deux images suivantes pour comparer.
Il suffit pour cela d’activer le plugin Chosen (Configuration générale du site > Gestion des plugins), puis de configurer le plugin (Les squelettes > Chosen) en activant l’utilisation de Chosen dans le site public et en spécifiant les éléments de formulaires à améliorer, par exemple select[multiple] pour les listes à sélection multiple (...) -
Support audio et vidéo HTML5
10 avril 2011MediaSPIP 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 (10669)
-
dockerized python application takes a long time to trim a video with ffmpeg
15 avril 2024, par Ukpa UchechiThe project trims YouTube videos.


When I ran the ffmpeg command on the terminal, it didn't take too long to respond. The code below returns the trimmed video to the front end but it takes too long to respond. A 10 mins trim length takes about 5mins to respond. I am missing something, but I can't pinpoint the issue.


backend


main.py


import os

from flask import Flask, request, send_file
from flask_cors import CORS, cross_origin


app = Flask(__name__)
cors = CORS(app)


current_directory = os.getcwd()
folder_name = "youtube_videos"
save_path = os.path.join(current_directory, folder_name)
output_file_path = os.path.join(save_path, 'video.mp4')

os.makedirs(save_path, exist_ok=True)

def convert_time_seconds(time_str):
 hours, minutes, seconds = map(int, time_str.split(':'))
 total_seconds = (hours * 3600) + (minutes * 60) + seconds

 return total_seconds
def convert_seconds_time(total_seconds):
 new_hours = total_seconds // 3600
 total_seconds %= 3600
 new_minutes = total_seconds // 60
 new_seconds = total_seconds % 60

 new_time_str = f'{new_hours:02}:{new_minutes:02}:{new_seconds:02}'

 return new_time_str
def add_seconds_to_time(time_str, seconds_to_add):
 total_seconds = convert_time_seconds(time_str)

 total_seconds -= seconds_to_add
 new_time_str = convert_seconds_time(total_seconds)

 return new_time_str

def get_length(start_time, end_time):
 start_time_seconds = convert_time_seconds(start_time)
 end_time_seconds = convert_time_seconds(end_time)

 length = end_time_seconds - start_time_seconds

 length_str = convert_seconds_time(length)
 return length_str
 
def download_url(url):
 command = [
 "yt-dlp",
 "-g",
 url
 ]
 
 try:
 links = subprocess.run(command, capture_output=True, text=True, check=True)
 
 video, audio = links.stdout.strip().split("\n")
 
 return video, audio

 except subprocess.CalledProcessError as e:
 print(f"Command failed with return code {e.returncode}.")
 print(f"Error output: {e.stderr}")
 return None
 except ValueError:
 print("Error: Could not parse video and audio links.")
 return None
 


def download_trimmed_video(video_link, audio_link, start_time, end_time):
 new_start_time = add_seconds_to_time(start_time, 30)
 new_end_time = get_length(start_time, end_time)

 if os.path.exists(output_file_path):
 os.remove(output_file_path)


 command = [
 'ffmpeg',
 '-ss', new_start_time + '.00',
 '-i', video_link,
 '-ss', new_start_time + '.00',
 '-i', audio_link,
 '-map', '0:v',
 '-map', '1:a',
 '-ss', '30',
 '-t', new_end_time + '.00',
 '-c:v', 'libx264',
 '-c:a', 'aac',
 output_file_path
 ]
 try:
 result = subprocess.run(command, capture_output=True, text=True, check=True)

 if result.returncode == 0:
 return "Trimmed video downloaded successfully!"
 else:
 return "Error occurred while downloading trimmed video"
 except subprocess.CalledProcessError as e:
 print(f"Command failed with return code {e.returncode}.")
 print(f"Error output: {e.stderr}")


app = Flask(__name__)


@app.route('/trimvideo', methods =["POST"])
@cross_origin()
def trim_video():
 print("here")
 data = request.get_json()
 video_link, audio_link = download_url(data["url"])
 if video_link and audio_link:
 print("Downloading trimmed video...")
 download_trimmed_video(video_link, audio_link, data["start_time"], data["end_time"])
 response = send_file(output_file_path, as_attachment=True, download_name='video.mp4')
 
 response.status_code = 200

 return response
 else:
 return "Error downloading video", 400

 




if __name__ == '__main__':
 app.run(debug=True, port=5000, host='0.0.0.0')



dockerfile


FROM ubuntu:latest

# Update the package list and install wget and ffmpeg
RUN apt-get update \
 && apt-get install -y wget ffmpeg python3 python3-pip \
 && rm -rf /var/lib/apt/lists/*

# Download the latest version of yt-dlp and install it
RUN wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -O /usr/local/bin/yt-dlp \
 && chmod a+rx /usr/local/bin/yt-dlp

WORKDIR /app

COPY main.py /app/
COPY requirements.txt /app/


RUN pip install --no-cache-dir -r requirements.txt


# Set the default command
CMD ["python3", "main.py"]



requirements.txt


blinker==1.7.0
click==8.1.7
colorama==0.4.6
Flask==3.0.3
Flask-Cors==4.0.0
itsdangerous==2.1.2
Jinja2==3.1.3
MarkupSafe==2.1.5
Werkzeug==3.0.2



frontend


App.js



import React, { useState } from 'react';
import './App.css';
import axios from 'axios';
async function handleSubmit(event, url, start_time, end_time, setVideoUrl, setIsSubmitted){
 event.preventDefault();

 if( url && start_time && end_time){

 try {
 setIsSubmitted(true);
 const response = await axios.post('http://127.0.0.1:5000/trimvideo', {
 url: url,
 start_time: start_time,
 end_time: end_time
 },
 {
 responseType: 'blob',
 headers: {'Content-Type': 'application/json'}
 }
 )
 const blob = new Blob([response.data], { type: 'video/mp4' });
 const newurl = URL.createObjectURL(blob);


 setVideoUrl(newurl);
 } catch (error) {
 console.error('Error trimming video:', error);
 }

 } else {
 alert('Please fill all the fields');
 }
}


function App() {
 const [url, setUrl] = useState('');
 const [startTime, setStartTime] = useState('');
 const [endTime, setEndTime] = useState('');
 const [videoUrl, setVideoUrl] = useState('');
 const [isSubmitted, setIsSubmitted] = useState(false);
 return (
 <div classname="App">
 <div classname="app-header">TRIM AND DOWNLOAD YOUR YOUTUBE VIDEO HERE</div>
 <input classname="input-url" placeholder="'Enter" value="{url}" />setUrl(e.target.value)}/>
 <div classname="input-container">
 <input classname="start-time-url" placeholder="start time" value="{startTime}" />setStartTime(e.target.value)}/>
 <input classname="end-time-url" placeholder="end time" value="{endTime}" />setEndTime(e.target.value)}/>
 
 </div>
 {
 !isSubmitted && <button>> handleSubmit(event, url, startTime, endTime, setVideoUrl, setIsSubmitted)} className='trim-button'>Trim</button>
 }

 {
 ( isSubmitted && !videoUrl) && <div classname="dot-pulse"></div>
 }


 {
 videoUrl && <video controls="controls" autoplay="autoplay" width="500" height="360">
 <source src="{videoUrl}" type="'video/mp4'"></source>
 </video>
 }

 
 </div>
 );
}

export default App;



-
Get the maximum frequency of an audio spectrum
6 avril, par milahuI want to detect the cutoff frequency of the AAC audio encoder used to compress an M4A audio file.


This cutoff frequency (or maximum frequency) is an indicator of audio quality.
High-quality audio has a cutoff around 20KHz (fullband),
medium-quality audio has a cutoff around 14KHz (superwideband),
low-quality audio has a cutoff around 7KHz (wideband),
super-low-quality audio has a cutoff around 3KHz (narrowband).
See also : voice frequency


Example spectrum of a 2 hours movie, generated with
sox
, with a maximum frequency around 19.6KHz :



The program should ignore noise below a certain loudness, for example -80dB.


Here is a Python script generated by deepseek.com but it returns 0.2KHz instead of 19.6KHz.


#!/usr/bin/env python3

# get the maximum frequency
# of an audio spectrum
# as an indicator
# of the actual audio quality

# generated by deepseek.com

# prompt
"""
create a python script
to detect the maximum frequency 
in an m4a audio file.
that maximum frequency is produced
by the lowpass filter
of the aac audio encoder.
high-quality audio
has a maximum frequency
around 20 KHz (fullband),
low-quality audio
has a maximum frequency
around 3 KHz (narrowband).
use ffmpeg to decode the audio
to pcm
in chunks of 10 seconds.
for each chunk:
detect the local maximum,
print the local maximum
and the chunk time
with the format
f"t={t}sec f={f}KHz",
update the global maximum.
to detect the local maximum,
remove the noise floor
around -110dB,
then find the maximum frequency
in the spectrum.
accept some command line options:
--ss n:
pass as "-ss n" to ffmpeg.
--to n:
pass as "-to n" to ffmpeg.
both -ss and -to args
must come before the -i arg
for ffmpeg input seeking.
print all frequencies in KHz.
add a shebang line before the script,
spaced by an empty line.
do not recode the audio with ffmpeg.
use ffprobe to get the input samplerate,
usually 48KHz or 44.1KHz.
create a python class,
so we dont have to pass all parameters to functions.
add a command line option to select the audio track id, by default zero.
"""

#!/usr/bin/env python3

import argparse
import numpy as np
import subprocess
import sys
from tempfile import NamedTemporaryFile


class AudioAnalyzer:
 def __init__(self, input_file, audio_track=0, start_time=None, end_time=None):
 self.input_file = input_file
 self.audio_track = audio_track
 self.start_time = start_time
 self.end_time = end_time
 self.sample_rate = self._get_sample_rate()
 self.global_max_freq = 0
 self.global_max_time = 0

 def _get_sample_rate(self):
 cmd = [
 'ffprobe',
 '-v', 'error',
 '-select_streams', f'a:{self.audio_track}',
 '-show_entries', 'stream=sample_rate',
 '-of', 'default=noprint_wrappers=1:nokey=1',
 self.input_file
 ]
 result = subprocess.run(cmd, capture_output=True, text=True)
 return float(result.stdout.strip())

 def _get_ffmpeg_command(self):
 cmd = [
 'ffmpeg',
 '-hide_banner',
 '-loglevel', 'error',
 ]
 
 if self.start_time is not None:
 cmd.extend(['-ss', str(self.start_time)])
 if self.end_time is not None:
 cmd.extend(['-to', str(self.end_time)])
 
 cmd.extend([
 '-i', self.input_file,
 '-map', f'0:a:{self.audio_track}',
 '-ac', '1', # convert to mono
 '-f', 'f32le', # 32-bit float PCM
 '-'
 ])
 
 return cmd

 def analyze(self, chunk_size=10):
 ffmpeg_cmd = self._get_ffmpeg_command()
 
 with subprocess.Popen(ffmpeg_cmd, stdout=subprocess.PIPE) as process:
 chunk_samples = int(chunk_size * self.sample_rate)
 bytes_per_sample = 4 # 32-bit float
 chunk_bytes = chunk_samples * bytes_per_sample
 
 current_time = self.start_time if self.start_time is not None else 0
 
 while True:
 raw_data = process.stdout.read(chunk_bytes)
 if not raw_data:
 break
 
 samples = np.frombuffer(raw_data, dtype=np.float32)
 if len(samples) == 0:
 continue
 
 local_max_freq = self._analyze_chunk(samples)
 
 print(f"t={current_time:.1f}sec f={local_max_freq:.1f}KHz")
 
 if local_max_freq > self.global_max_freq:
 self.global_max_freq = local_max_freq
 self.global_max_time = current_time
 
 current_time += chunk_size

 def _analyze_chunk(self, samples):
 # Apply Hanning window
 window = np.hanning(len(samples))
 windowed_samples = samples * window
 
 # Compute FFT
 fft = np.fft.rfft(windowed_samples)
 magnitudes = np.abs(fft)
 
 # Convert to dB
 eps = 1e-10 # avoid log(0)
 magnitudes_db = 20 * np.log10(magnitudes + eps)
 
 # Frequency bins
 freqs = np.fft.rfftfreq(len(samples), 1.0 / self.sample_rate) / 1000 # in KHz
 
 # Remove noise floor (-110dB)
 threshold = -110
 valid_indices = magnitudes_db > threshold
 valid_freqs = freqs[valid_indices]
 valid_magnitudes = magnitudes_db[valid_indices]
 
 if len(valid_freqs) == 0:
 return 0
 
 # Find frequency with maximum magnitude
 max_idx = np.argmax(valid_magnitudes)
 max_freq = valid_freqs[max_idx]
 
 return max_freq


def main():
 parser = argparse.ArgumentParser(description='Detect maximum frequency in audio file')
 parser.add_argument('input_file', help='Input audio file (m4a)')
 parser.add_argument('--ss', type=float, help='Start time in seconds')
 parser.add_argument('--to', type=float, help='End time in seconds')
 parser.add_argument('--track', type=int, default=0, help='Audio track ID (default: 0)')
 args = parser.parse_args()

 analyzer = AudioAnalyzer(
 input_file=args.input_file,
 audio_track=args.track,
 start_time=args.ss,
 end_time=args.to
 )
 
 print(f"Analyzing audio file: {args.input_file}")
 print(f"Sample rate: {analyzer.sample_rate/1000:.1f} KHz")
 print(f"Audio track: {args.track}")
 if args.ss is not None:
 print(f"Start time: {args.ss} sec")
 if args.to is not None:
 print(f"End time: {args.to} sec")
 print("---")
 
 analyzer.analyze()
 
 print("---")
 print(f"Global maximum: t={analyzer.global_max_time:.1f}sec f={analyzer.global_max_freq:.1f}KHz")
 
 if analyzer.global_max_freq > 15:
 print("Quality: Fullband (high quality)")
 elif analyzer.global_max_freq > 5:
 print("Quality: Wideband (medium quality)")
 else:
 print("Quality: Narrowband (low quality)")


if __name__ == '__main__':
 main()



Similar question :
How to find the max frequency at a certain db in a fft signal



edited by kesh


Here is an example psd indicating the fullband quality with a psd dropoff around 20 kHz.




-
Building FFMPEG on UBUNTU facing issue while compiling common.mak file
9 juin 2016, par sumit singhI am compiling the ffmpeg library i am facing some issues while compiling this.
I follow the steps of compilation form here.But i am failed to compile.
The issues are as below.WARNING: /home/sumit/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin/arm-linux-androideabi-pkg-config not found, library detection may fail.
libavcodec/bsf_list.c is unchanged
libavformat/protocol_list.c is unchanged
common.mak:26: *** unterminated call to function `foreach': missing `)'. Stop.
common.mak:26: *** unterminated call to function `foreach': missing `)'. Stop.
common.mak:26: *** unterminated call to function `foreach': missing `)'. Stop.
sumit@sumit-H81M-S:~/android-ndk-r10e/sources/ffmpeg$here is my build_android.sh file-
#!/bin/bash
NDK=$HOME/android-ndk-r10e
SYSROOT=$NDK/platforms/android-19/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86
function build_one
{
./configure --prefix=$PREFIX --enable-shared --disable-static --disable-doc --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-avdevice --disable-doc --disable-symver --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- --target-os=linux --arch=arm --enable-cross-compile --sysroot=$SYSROOT --extra-cflags="-Os -fpic $ADDI_CFLAGS" --extra-ldflags="$ADDI_LDFLAGS"
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_onecommon.mak-
#
# common bits used by all libraries
#
# first so "all" becomes default target
all: all-yes
DEFAULT_YASMD=.dbg
ifeq ($(DBG),1)
YASMD=$(DEFAULT_YASMD)
else
YASMD=
endif
ifndef SUBDIR
ifndef V
Q = @
ECHO = printf "$(1)\t%s\n" $(2)
BRIEF = CC CXX OBJCC HOSTCC HOSTLD AS YASM AR LD STRIP CP WINDRES
SILENT = DEPCC DEPHOSTCC DEPAS DEPYASM RANLIB RM
MSG = $@
M = @$(call ECHO,$(TAG),$@);
$(foreach VAR,$(BRIEF), \
$(eval override $(VAR) = @$$(call ECHO,$(VAR),$$(MSG)); $($(VAR))))
$(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR))))
$(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_DIR)/%=%)); $(INSTALL))
endif
ALLFFLIBS = avcodec avdevice avfilter avformat avresample avutil postproc swscale swresample
# NASM requires -I path terminated with /
IFLAGS := -I. -I$(SRC_LINK)/
CPPFLAGS := $(IFLAGS) $(CPPFLAGS)
CFLAGS += $(ECFLAGS)
CCFLAGS = $(CPPFLAGS) $(CFLAGS)
OBJCFLAGS += $(EOBJCFLAGS)
OBJCCFLAGS = $(CPPFLAGS) $(CFLAGS) $(OBJCFLAGS)
ASFLAGS := $(CPPFLAGS) $(ASFLAGS)
CXXFLAGS += $(CPPFLAGS) $(CFLAGS)
YASMFLAGS += $(IFLAGS:%=%/) -Pconfig.asm
HOSTCCFLAGS = $(IFLAGS) $(HOSTCPPFLAGS) $(HOSTCFLAGS)
LDFLAGS := $(ALLFFLIBS:%=$(LD_PATH)lib%) $(LDFLAGS)
define COMPILE
$(call $(1)DEP,$(1))
$($(1)) $($(1)FLAGS) $($(1)_DEPFLAGS) $($(1)_C) $($(1)_O) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<)
endef
COMPILE_C = $(call COMPILE,CC)
COMPILE_CXX = $(call COMPILE,CXX)
COMPILE_S = $(call COMPILE,AS)
COMPILE_M = $(call COMPILE,OBJCC)
COMPILE_HOSTC = $(call COMPILE,HOSTCC)
%.o: %.c
$(COMPILE_C)
%.o: %.cpp
$(COMPILE_CXX)
%.o: %.m
$(COMPILE_M)
%.s: %.c
$(CC) $(CCFLAGS) -S -o $@ $<
%.o: %.S
$(COMPILE_S)
%_host.o: %.c
$(COMPILE_HOSTC)
%.o: %.rc
$(WINDRES) $(IFLAGS) --preprocessor "$(DEPWINDRES) -E -xc-header -DRC_INVOKED $(CC_DEPFLAGS)" -o $@ $<
%.i: %.c
$(CC) $(CCFLAGS) $(CC_E) $<
%.h.c:
$(Q)echo '#include "$*.h"' >$@
%.ver: %.v
$(Q)sed 's/$$MAJOR/$($(basename $(@F))_VERSION_MAJOR)/' $^ | sed -e 's/:/:\
/' -e 's/; /;\
/g' > $@
%.c %.h: TAG = GEN
# Dummy rule to stop make trying to rebuild removed or renamed headers
%.h:
@:
# Disable suffix rules. Most of the builtin rules are suffix rules,
# so this saves some time on slow systems.
.SUFFIXES:
# Do not delete intermediate files from chains of implicit rules
$(OBJS):
endif
include $(SRC_PATH)/arch.mak
OBJS += $(OBJS-yes)
SLIBOBJS += $(SLIBOBJS-yes)
FFLIBS := $($(NAME)_FFLIBS) $(FFLIBS-yes) $(FFLIBS)
TESTPROGS += $(TESTPROGS-yes)
LDLIBS = $(FFLIBS:%=%$(BUILDSUF))
FFEXTRALIBS := $(LDLIBS:%=$(LD_LIB)) $(EXTRALIBS)
OBJS := $(sort $(OBJS:%=$(SUBDIR)%))
SLIBOBJS := $(sort $(SLIBOBJS:%=$(SUBDIR)%))
TESTOBJS := $(TESTOBJS:%=$(SUBDIR)%) $(TESTPROGS:%=$(SUBDIR)%-test.o)
TESTPROGS := $(TESTPROGS:%=$(SUBDIR)%-test$(EXESUF))
HOSTOBJS := $(HOSTPROGS:%=$(SUBDIR)%.o)
HOSTPROGS := $(HOSTPROGS:%=$(SUBDIR)%$(HOSTEXESUF))
TOOLS += $(TOOLS-yes)
TOOLOBJS := $(TOOLS:%=tools/%.o)
TOOLS := $(TOOLS:%=tools/%$(EXESUF))
HEADERS += $(HEADERS-yes)
PATH_LIBNAME = $(foreach NAME,$(1),lib$(NAME)/$($(2)LIBNAME))
DEP_LIBS := $(foreach lib,$(FFLIBS),$(call PATH_LIBNAME,$(lib),$(CONFIG_SHARED:yes=S)))
STATIC_DEP_LIBS := $(foreach lib,$(FFLIBS),$(call PATH_LIBNAME,$(lib)))
SRC_DIR := $(SRC_PATH)/lib$(NAME)
ALLHEADERS := $(subst $(SRC_DIR)/,$(SUBDIR),$(wildcard $(SRC_DIR)/*.h $(SRC_DIR)/$(ARCH)/*.h))
SKIPHEADERS += $(ARCH_HEADERS:%=$(ARCH)/%) $(SKIPHEADERS-)
SKIPHEADERS := $(SKIPHEADERS:%=$(SUBDIR)%)
HOBJS = $(filter-out $(SKIPHEADERS:.h=.h.o),$(ALLHEADERS:.h=.h.o))
checkheaders: $(HOBJS)
.SECONDARY: $(HOBJS:.o=.c)
alltools: $(TOOLS)
$(HOSTOBJS): %.o: %.c
$(COMPILE_HOSTC)
$(HOSTPROGS): %$(HOSTEXESUF): %.o
$(HOSTLD) $(HOSTLDFLAGS) $(HOSTLD_O) $^ $(HOSTLIBS)
$(OBJS): | $(sort $(dir $(OBJS)))
$(HOBJS): | $(sort $(dir $(HOBJS)))
$(HOSTOBJS): | $(sort $(dir $(HOSTOBJS)))
$(SLIBOBJS): | $(sort $(dir $(SLIBOBJS)))
$(TESTOBJS): | $(sort $(dir $(TESTOBJS)))
$(TOOLOBJS): | tools
OBJDIRS := $(OBJDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(SLIBOBJS) $(TESTOBJS))
CLEANSUFFIXES = *.d *.o *~ *.h.c *.map *.ver *.ver-sol2 *.ho *.gcno *.gcda *$(DEFAULT_YASMD).asm
DISTCLEANSUFFIXES = *.pc
LIBSUFFIXES = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a
define RULES
clean::
$(RM) $(HOSTPROGS)
$(RM) $(TOOLS)
endef
$(eval $(RULES))
-include $(wildcard $(OBJS:.o=.d) $(HOSTOBJS:.o=.d) $(TESTOBJS:.o=.d) $(HOBJS:.o=.d) $(SLIBOBJS:.o=.d)) $(OBJS:.o=$(DEFAULT_YASMD).d)