Skip to content

Commit caea2be

Browse files
v5.0.0 refactoring
1 parent 0519df1 commit caea2be

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2118
-575
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use Kiwilan\Audio\Models\AudioCover;
1111
use Kiwilan\Audio\Models\AudioMetadata;
1212

13-
class Audio
13+
class AudioOld
1414
{
1515
/**
1616
* @param array<string, string[]> $raw_all

.vscode/old/src/Core/AudioCore.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespace Kiwilan\Audio\Core;
4+
5+
class AudioCore
6+
{
7+
public function __construct(
8+
public readonly ?AudioCoreCover $cover = null,
9+
public readonly bool $has_cover = false,
10+
11+
// public readonly ?string $creation_date = null,
12+
13+
protected ?string $album = null, // The Wall
14+
protected ?string $album_artist = null, // Pink Floyd
15+
protected ?string $artist = null, // Syd Barrett;Nick Mason;Roger Waters;Richard Wright;David Gilmour
16+
protected ?string $asin = null, // B008Y43GBY
17+
protected ?string $comment = null, // Recorded at Abbey Road Studios
18+
protected ?string $compilation = null, // 1
19+
protected ?string $composer = null, // Syd Barrett
20+
protected ?string $copyright = null, // © 1979 Pink Floyd
21+
protected ?string $description = null, // The Wall is the eleventh studio album by the English rock band Pink Floyd
22+
protected ?string $disc = null, // 1/2
23+
protected ?string $encoded_by = null, // iTunes
24+
protected ?string $encoder = null, // Lavf62.3.100
25+
protected ?string $genre = null, // Progressive Rock;Rock Opera
26+
protected ?string $isbn = null, // 9780007496785
27+
protected ?string $language = null, // English
28+
protected ?string $lyrics = null, // Hey! Teachers! Leave them kids alone!
29+
protected ?string $publisher = null, // Pink Floyd Music Publishers Ltd.
30+
protected ?string $series = null, // The Wall Saga
31+
protected ?string $series_part = null, // 1
32+
protected ?string $subtitle = null, // All in all, it's just another brick in the wall.
33+
protected ?string $synopsis = null, // The Wall is one of the most iconic concept albums and rock operas in music history.
34+
protected ?string $title = null, // Another Brick in the Wall, Part 1
35+
protected ?string $track = null, // 3/13
36+
protected ?string $date = null, // 1979-11-30
37+
) {}
38+
39+
public function toArray(): array
40+
{
41+
// parse all properties
42+
$properties = get_object_vars($this);
43+
44+
// filter out null values
45+
$properties = array_filter($properties, fn ($value) => $value !== null);
46+
$properties = array_filter($properties, fn ($value) => $value !== '');
47+
48+
return $properties;
49+
}
50+
51+
// public function parseCompilation(AudioCore $core): ?string
52+
// {
53+
// if ($core->is_compilation === null) {
54+
// return null;
55+
// }
56+
57+
// return $core->is_compilation ? '1' : '0';
58+
// }
59+
}
Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,53 +4,8 @@
44

55
use Kiwilan\Audio\Id3\Tag;
66

7-
class AudioCore
7+
class Id3Core
88
{
9-
public function __construct(
10-
public ?string $title = null,
11-
public ?string $artist = null,
12-
public ?string $album = null,
13-
public ?string $genre = null,
14-
public ?int $year = null,
15-
public ?string $track_number = null,
16-
public ?string $comment = null,
17-
public ?string $album_artist = null,
18-
public ?string $composer = null,
19-
public ?string $disc_number = null,
20-
public ?bool $is_compilation = null,
21-
public ?string $creation_date = null,
22-
public ?string $copyright = null,
23-
public ?string $encoding_by = null,
24-
public ?string $encoding = null,
25-
public ?string $description = null,
26-
public ?string $synopsis = null,
27-
public ?string $language = null,
28-
public ?string $lyrics = null,
29-
public bool $has_cover = false,
30-
public ?AudioCoreCover $cover = null,
31-
) {}
32-
33-
public function toArray(): array
34-
{
35-
// parse all properties
36-
$properties = get_object_vars($this);
37-
38-
// filter out null values
39-
$properties = array_filter($properties, fn ($value) => $value !== null);
40-
$properties = array_filter($properties, fn ($value) => $value !== '');
41-
42-
return $properties;
43-
}
44-
45-
private function parseCompilation(AudioCore $core): ?string
46-
{
47-
if ($core->is_compilation === null) {
48-
return null;
49-
}
50-
51-
return $core->is_compilation ? '1' : '0';
52-
}
53-
549
public static function toId3v2(AudioCore $core): Tag\Id3TagAudioV2
5510
{
5611
return new Tag\Id3TagAudioV2(
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace Kiwilan\Audio\Engines;
4+
5+
use Kiwilan\Audio\Core\AudioException;
6+
use Kiwilan\Audio\Utils\AudioProcess;
7+
8+
class ExiftoolEngine extends AudioEngine
9+
{
10+
public static function read(string $path)
11+
{
12+
$self = new self;
13+
14+
if (! AudioProcess::isCommandAvailable('exiftool -v')) {
15+
throw new AudioException('`exiftool` binary not available.');
16+
}
17+
18+
$output = AudioProcess::execute([
19+
'exiftool', '-json',
20+
$path,
21+
]);
22+
$data = json_decode($output, true);
23+
24+
return $data;
25+
}
26+
27+
public function toArray(): array
28+
{
29+
throw new \Exception('Not implemented');
30+
}
31+
32+
public function getCover(string $path)
33+
{
34+
$cover = shell_exec('exiftool -b -Picture '.escapeshellarg($path));
35+
36+
file_put_contents('cover.jpg', $cover);
37+
}
38+
}
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
<?php
2+
3+
namespace Kiwilan\Audio\Engines;
4+
5+
use Kiwilan\Audio\Core\AudioCore;
6+
use Kiwilan\Audio\Utils\AudioProcess;
7+
8+
class FfmpegEngine extends AudioEngine
9+
{
10+
public static function read(string $path)
11+
{
12+
$self = new self;
13+
14+
$self->process = AudioProcess::execute([
15+
'ffprobe',
16+
'-v', 'quiet',
17+
'-print_format', 'json',
18+
'-show_format',
19+
'-show_streams',
20+
$path,
21+
]);
22+
ray($self->process);
23+
if (! $self->process->isSuccessful()) {
24+
return $self;
25+
}
26+
27+
$self->output = $self->toAssociativeArray($self->process->getOutput());
28+
$self->json = json_encode($self->output, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
29+
30+
return $self;
31+
}
32+
33+
private function extractKey(mixed $data, string $key): mixed
34+
{
35+
if (array_key_exists($key, $data)) {
36+
return $data[$key];
37+
}
38+
39+
return null;
40+
}
41+
42+
public function toArray(): array
43+
{
44+
throw new \Exception('Not implemented');
45+
}
46+
47+
public function toAudioCore(): ?AudioCore
48+
{
49+
$format = $this->extractKey($this->output, 'format');
50+
if (! $format) {
51+
return null;
52+
}
53+
54+
$tags = $this->extractKey($format, 'tags');
55+
if (! $tags) {
56+
return null;
57+
}
58+
59+
return new AudioCore(
60+
album: $this->extractKey($tags, 'album'),
61+
album_artist: $this->extractKey($tags, 'album_artist'),
62+
artist: $this->extractKey($tags, 'artist'),
63+
comment: $this->extractKey($tags, 'comment'),
64+
composer: $this->extractKey($tags, 'composer'),
65+
copyright: $this->extractKey($tags, 'copyright'),
66+
cover: null,
67+
creation_date: null,
68+
description: $this->extractKey($tags, 'DESCRIPTION'),
69+
disc_number: $this->extractKey($tags, 'disc'),
70+
has_cover: false,
71+
is_compilation: $this->extractKey($tags, 'compilation'),
72+
encoding: $this->extractKey($tags, 'encoder'),
73+
encoding_by: $this->extractKey($tags, 'encoded_by'),
74+
genre: $this->extractKey($tags, 'genre'),
75+
language: $this->extractKey($tags, 'language'),
76+
lyrics: $this->extractKey($tags, 'LYRICS'),
77+
synopsis: $this->extractKey($tags, 'TDES'),
78+
title: $this->extractKey($tags, 'title'),
79+
track_number: $this->extractKey($tags, 'track'),
80+
year: $this->extractKey($tags, 'date'),
81+
subtitle: $this->extractKey($tags, 'TIT3'),
82+
publisher: $this->extractKey($tags, 'publisher'),
83+
asin: $this->extractKey($tags, 'ASIN'),
84+
isbn: $this->extractKey($tags, 'ISBN'),
85+
series: $this->extractKey($tags, 'SERIES'),
86+
series_part: $this->extractKey($tags, 'SERIES-PART'),
87+
);
88+
}
89+
90+
// public function getMetadata($filePath)
91+
// {
92+
// // Échapper le chemin pour la sécurité
93+
// $filePathEscaped = escapeshellarg($filePath);
94+
95+
// // Commande ffprobe
96+
// $cmd = "ffprobe -v quiet -print_format json -show_format -show_streams $filePathEscaped";
97+
98+
// // Exécution
99+
// $output = shell_exec($cmd);
100+
101+
// // Transformation en tableau PHP
102+
// return json_decode($output, true);
103+
// }
104+
105+
// public function mp3HasCover(string $filePath): bool
106+
// {
107+
// $file = escapeshellarg($filePath);
108+
109+
// $cmd = "ffprobe -v quiet -print_format json -show_streams $file";
110+
// $json = shell_exec($cmd);
111+
// $data = json_decode($json, true);
112+
113+
// if (! isset($data['streams'])) {
114+
// return false;
115+
// }
116+
117+
// foreach ($data['streams'] as $stream) {
118+
// if (
119+
// isset($stream['disposition']['attached_pic'])
120+
// && $stream['disposition']['attached_pic'] == 1
121+
// ) {
122+
// return true;
123+
// }
124+
// }
125+
126+
// return false;
127+
// }
128+
129+
// public function mp3ExtractRawCover(string $filePath, string $outputTempPath): bool
130+
// {
131+
// $file = escapeshellarg($filePath);
132+
// $output = escapeshellarg($outputTempPath);
133+
134+
// // -map 0:v sélectionne l’image ID3
135+
// $cmd = "ffmpeg -i $file -an -vcodec copy -map 0:v -y $output 2>&1";
136+
// shell_exec($cmd);
137+
138+
// return file_exists($output);
139+
// }
140+
141+
// public function extractCoverWithMime(string $mp3Path, string $outputDirectory): ?string
142+
// {
143+
// if (! mp3HasCover($mp3Path)) {
144+
// return null;
145+
// }
146+
147+
// // Fichier temporaire sans extension
148+
// $temp = rtrim($outputDirectory, '/').'/cover_tmp';
149+
150+
// if (! mp3ExtractRawCover($mp3Path, $temp)) {
151+
// return null;
152+
// }
153+
154+
// // Détecter le mimetype
155+
// $mime = mime_content_type($temp);
156+
157+
// // Choix de l’extension
158+
// $ext = match ($mime) {
159+
// 'image/jpeg' => 'jpg',
160+
// 'image/png' => 'png',
161+
// default => null,
162+
// };
163+
164+
// if ($ext === null) {
165+
// // Type inconnu
166+
// unlink($temp);
167+
168+
// return null;
169+
// }
170+
171+
// $finalPath = rtrim($outputDirectory, '/')."/cover.$ext";
172+
173+
// // Déplacer avec la bonne extension
174+
// rename($temp, $finalPath);
175+
176+
// return $finalPath;
177+
// }
178+
179+
}

0 commit comments

Comments
 (0)