mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 09:38:57 +01:00
Allow converting URLs and streams
This commit is contained in:
parent
df1e6b2ba8
commit
a9aeaedaf4
@ -388,6 +388,7 @@ Want to add your own open-source project to this list? [Click here!](https://doc
|
|||||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.hideChatJoinRequest.html" name="messages.hideChatJoinRequest">Dismiss or approve a chat join request related to a specific chat or channel: messages.hideChatJoinRequest</a>
|
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.hideChatJoinRequest.html" name="messages.hideChatJoinRequest">Dismiss or approve a chat join request related to a specific chat or channel: messages.hideChatJoinRequest</a>
|
||||||
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.hideAllChatJoinRequests.html" name="messages.hideAllChatJoinRequests">Dismiss or approve all join requests related to a specific chat or channel: messages.hideAllChatJoinRequests</a>
|
* <a href="https://docs.madelineproto.xyz/API_docs/methods/messages.hideAllChatJoinRequests.html" name="messages.hideAllChatJoinRequests">Dismiss or approve all join requests related to a specific chat or channel: messages.hideAllChatJoinRequests</a>
|
||||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtoresponse-array-string-filecallbackinterface-danog-madelineproto-eventhandler-message-messagemedia-amp-http-server-request-request-callable-cb-null-null-int-size-null-null-string-mime-null-null-string-name-null-amp-http-server-response" name="downloadToResponse">Download file to amphp/http-server response: downloadToResponse</a>
|
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtoresponse-array-string-filecallbackinterface-danog-madelineproto-eventhandler-message-messagemedia-amp-http-server-request-request-callable-cb-null-null-int-size-null-null-string-mime-null-null-string-name-null-amp-http-server-response" name="downloadToResponse">Download file to amphp/http-server response: downloadToResponse</a>
|
||||||
|
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtoreturnedstream-mixed-messagemedia-callable-cb-null-int-offset-0-int-end-1-amp-bytestream-readablestream" name="downloadToReturnedStream">Download file to an amphp stream, returning it: downloadToReturnedStream</a>
|
||||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtobrowser-array-string-filecallbackinterface-danog-madelineproto-eventhandler-message-messagemedia-null-callable-cb-null-null-int-size-null-null-string-name-null-null-string-mime-null-void" name="downloadToBrowser">Download file to browser: downloadToBrowser</a>
|
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtobrowser-array-string-filecallbackinterface-danog-madelineproto-eventhandler-message-messagemedia-null-callable-cb-null-null-int-size-null-null-string-name-null-null-string-mime-null-void" name="downloadToBrowser">Download file to browser: downloadToBrowser</a>
|
||||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtocallable-mixed-messagemedia-callable-filecallbackinterface-callable-callable-cb-null-bool-seekable-true-int-offset-0-int-end-1-int-part_size-null-mixed" name="downloadToCallable">Download file to callable: downloadToCallable</a>
|
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtocallable-mixed-messagemedia-callable-filecallbackinterface-callable-callable-cb-null-bool-seekable-true-int-offset-0-int-end-1-int-part_size-null-mixed" name="downloadToCallable">Download file to callable: downloadToCallable</a>
|
||||||
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtodir-mixed-messagemedia-string-filecallbackinterface-dir-callable-cb-null-mixed" name="downloadToDir">Download file to directory: downloadToDir</a>
|
* <a href="https://docs.madelineproto.xyz/PHP/danog/MadelineProto/API.html#downloadtodir-mixed-messagemedia-string-filecallbackinterface-dir-callable-cb-null-mixed" name="downloadToDir">Download file to directory: downloadToDir</a>
|
||||||
|
@ -121,3 +121,5 @@ final class MemoryArray extends ArrayIterator implements DbArray
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class_alias(MemoryArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\MemoryArray');
|
@ -142,3 +142,5 @@ final class MysqlArray extends SqlArray
|
|||||||
");
|
");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class_alias(MysqlArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\MysqlArray');
|
@ -109,3 +109,5 @@ final class PostgresArray extends PostgresArrayBytea
|
|||||||
");
|
");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class_alias(PostgresArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\PostgresArray');
|
@ -127,3 +127,5 @@ class PostgresArrayBytea extends SqlArray
|
|||||||
");
|
");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class_alias(PostgresArrayBytea::class, '\\danog\\MadelineProto\\Db\\NullCache\\PostgresArrayBytea');
|
||||||
|
@ -155,3 +155,5 @@ final class RedisArray extends DriverArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class_alias(RedisArray::class, '\\danog\\MadelineProto\\Db\\NullCache\\RedisArray');
|
||||||
|
48
src/Ogg.php
48
src/Ogg.php
@ -19,10 +19,15 @@ declare(strict_types=1);
|
|||||||
namespace danog\MadelineProto;
|
namespace danog\MadelineProto;
|
||||||
|
|
||||||
use Amp\ByteStream\ReadableStream;
|
use Amp\ByteStream\ReadableStream;
|
||||||
use Amp\File\Whence;
|
use Amp\ByteStream\WritableStream;
|
||||||
|
use Amp\Http\Client\HttpClientBuilder;
|
||||||
|
use Amp\Http\Client\Request;
|
||||||
use AssertionError;
|
use AssertionError;
|
||||||
use danog\MadelineProto\Stream\BufferedStreamInterface;
|
use danog\MadelineProto\Stream\BufferedStreamInterface;
|
||||||
use danog\MadelineProto\Stream\BufferInterface;
|
use danog\MadelineProto\Stream\BufferInterface;
|
||||||
|
use danog\MadelineProto\Stream\Common\SimpleBufferedRawStream;
|
||||||
|
use danog\MadelineProto\Stream\ConnectionContext;
|
||||||
|
use danog\MadelineProto\Stream\Transport\PremadeStream;
|
||||||
use FFI;
|
use FFI;
|
||||||
use FFI\CData;
|
use FFI\CData;
|
||||||
use Webmozart\Assert\Assert;
|
use Webmozart\Assert\Assert;
|
||||||
@ -498,7 +503,7 @@ final class Ogg
|
|||||||
|
|
||||||
public static function convert(
|
public static function convert(
|
||||||
LocalFile|RemoteUrl|ReadableStream $wavIn,
|
LocalFile|RemoteUrl|ReadableStream $wavIn,
|
||||||
string $oggOut
|
LocalFile|WritableStream $oggOut
|
||||||
): void {
|
): void {
|
||||||
$opus = FFI::cdef('
|
$opus = FFI::cdef('
|
||||||
typedef struct OpusEncoder OpusEncoder;
|
typedef struct OpusEncoder OpusEncoder;
|
||||||
@ -542,23 +547,33 @@ final class Ogg
|
|||||||
$checkErr($opus->opus_encoder_ctl($encoder, self::OPUS_SET_BANDWIDTH_REQUEST, self::OPUS_BANDWIDTH_FULLBAND));
|
$checkErr($opus->opus_encoder_ctl($encoder, self::OPUS_SET_BANDWIDTH_REQUEST, self::OPUS_BANDWIDTH_FULLBAND));
|
||||||
$checkErr($opus->opus_encoder_ctl($encoder, self::OPUS_SET_BITRATE_REQUEST, 130*1000));
|
$checkErr($opus->opus_encoder_ctl($encoder, self::OPUS_SET_BITRATE_REQUEST, 130*1000));
|
||||||
|
|
||||||
$in = openFile($wavIn, 'r');
|
$in = $wavIn instanceof LocalFile
|
||||||
Assert::eq($in->read(length: 4), 'RIFF', "A .wav file must be provided!");
|
? openFile($wavIn->file, 'r')
|
||||||
$totalLength = \unpack('V', $in->read(length: 4))[1];
|
: (
|
||||||
Assert::eq($in->read(length: 4), 'WAVE');
|
$wavIn instanceof RemoteUrl
|
||||||
|
? HttpClientBuilder::buildDefault()->request(new Request($wavIn->url))->getBody()
|
||||||
|
: $wavIn
|
||||||
|
);
|
||||||
|
|
||||||
|
$ctx = (new ConnectionContext())->addStream(PremadeStream::class, $in)->addStream(SimpleBufferedRawStream::class);
|
||||||
|
/** @var SimpleBufferedRawStream */
|
||||||
|
$in = $ctx->getStream();
|
||||||
|
Assert::eq($in->bufferRead(length: 4), 'RIFF', "A .wav file must be provided!");
|
||||||
|
$totalLength = \unpack('V', $in->bufferRead(length: 4))[1];
|
||||||
|
Assert::eq($in->bufferRead(length: 4), 'WAVE');
|
||||||
do {
|
do {
|
||||||
$type = $in->read(length: 4);
|
$type = $in->bufferRead(length: 4);
|
||||||
$length = \unpack('V', $in->read(length: 4))[1];
|
$length = \unpack('V', $in->bufferRead(length: 4))[1];
|
||||||
if ($type === 'fmt ') {
|
if ($type === 'fmt ') {
|
||||||
Assert::eq($length, 16);
|
Assert::eq($length, 16);
|
||||||
$contents = $in->read(length: $length + ($length % 2));
|
$contents = $in->bufferRead(length: $length + ($length % 2));
|
||||||
$header = \unpack('vaudioFormat/vchannels/VsampleRate/VbyteRate/vblockAlign/vbitsPerSample', $contents);
|
$header = \unpack('vaudioFormat/vchannels/VsampleRate/VbyteRate/vblockAlign/vbitsPerSample', $contents);
|
||||||
Assert::eq($header['audioFormat'], 1);
|
Assert::eq($header['audioFormat'], 1);
|
||||||
Assert::eq($header['sampleRate'], 48000);
|
Assert::eq($header['sampleRate'], 48000);
|
||||||
} elseif ($type === 'data') {
|
} elseif ($type === 'data') {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
$in->seek($length, Whence::Current);
|
$in->bufferRead($length);
|
||||||
}
|
}
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|
||||||
@ -566,7 +581,9 @@ final class Ogg
|
|||||||
$chunkSize = (int) ($sampleCount * $header['channels'] * ($header['bitsPerSample'] >> 3));
|
$chunkSize = (int) ($sampleCount * $header['channels'] * ($header['bitsPerSample'] >> 3));
|
||||||
$shift = (int) \log($header['channels'] * ($header['bitsPerSample'] >> 3), 2);
|
$shift = (int) \log($header['channels'] * ($header['bitsPerSample'] >> 3), 2);
|
||||||
|
|
||||||
$out = openFile($oggOut, 'w');
|
$out = $oggOut instanceof LocalFile
|
||||||
|
? openFile($oggOut->file, 'w')
|
||||||
|
: $oggOut;
|
||||||
|
|
||||||
$writePage = function (int $header_type_flag, int $granule, int $streamId, int &$streamSeqno, string $packet) use ($out): void {
|
$writePage = function (int $header_type_flag, int $granule, int $streamId, int &$streamSeqno, string $packet) use ($out): void {
|
||||||
Assert::true(\strlen($packet) < 65025);
|
Assert::true(\strlen($packet) < 65025);
|
||||||
@ -638,19 +655,20 @@ final class Ogg
|
|||||||
|
|
||||||
$granule = 0;
|
$granule = 0;
|
||||||
$buf = FFI::cast(FFI::type('char*'), FFI::addr($opus->new('char[1024]')));
|
$buf = FFI::cast(FFI::type('char*'), FFI::addr($opus->new('char[1024]')));
|
||||||
while (!$in->eof()) {
|
do {
|
||||||
$chunk = \str_pad($in->read(length: $chunkSize), $chunkSize, "\0");
|
$chunkOrig = $in->bufferRead(length: $chunkSize);
|
||||||
|
$chunk = \str_pad($chunkOrig, $chunkSize, "\0");
|
||||||
$granuleDiff = \strlen($chunk) >> $shift;
|
$granuleDiff = \strlen($chunk) >> $shift;
|
||||||
$len = $opus->opus_encode($encoder, $chunk, $granuleDiff, $buf, 1024);
|
$len = $opus->opus_encode($encoder, $chunk, $granuleDiff, $buf, 1024);
|
||||||
$checkErr($len);
|
$checkErr($len);
|
||||||
$writePage(
|
$writePage(
|
||||||
$in->eof() ? self::EOS : 0,
|
\strlen($chunk) !== \strlen($chunkOrig) ? self::EOS : 0,
|
||||||
$granule += $granuleDiff,
|
$granule += $granuleDiff,
|
||||||
$streamId,
|
$streamId,
|
||||||
$seqno,
|
$seqno,
|
||||||
FFI::string($buf, $len)
|
FFI::string($buf, $len)
|
||||||
);
|
);
|
||||||
}
|
} while (\strlen($chunk) === \strlen($chunkOrig));
|
||||||
$opus->opus_encoder_destroy($encoder);
|
$opus->opus_encoder_destroy($encoder);
|
||||||
unset($buf, $encoder, $opus);
|
unset($buf, $encoder, $opus);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user