diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index d1c6825b0..d9361da9e 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -1492,7 +1492,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_player_message_today" = "Today at {time}";
 "lng_player_message_yesterday" = "Yesterday at {time}";
 "lng_player_message_date" = "{date} at {time}";
-"lng_player_cant_play" = "This file can't be played in Telegram Desktop.\n\nWould you like to download it and open it in an external player?";
+"lng_player_cant_stream" = "This file can't be played before it is fully downloaded.\n\nWould you like to download it?";
 "lng_player_download" = "Download";
 
 "lng_rights_edit_admin" = "Manage permissions";
diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp
index 7f439980d..246b91f7b 100644
--- a/Telegram/SourceFiles/data/data_document.cpp
+++ b/Telegram/SourceFiles/data/data_document.cpp
@@ -301,9 +301,6 @@ void DocumentOpenClickHandler::Open(
 		Core::App().showDocument(data, context);
 		location.accessDisable();
 		return;
-	} else if (data->inappPlaybackFailed()) {
-		::Data::HandleUnsupportedMedia(data, msgId);
-		return;
 	} else if (data->canBePlayed()) {
 		if (data->isAudioFile()
 			|| data->isVoiceMessage()
@@ -444,7 +441,7 @@ AuthSession &DocumentData::session() const {
 void DocumentData::setattributes(
 		const QVector<MTPDocumentAttribute> &attributes) {
 	_isImage = false;
-	_supportsStreaming = false;
+	_supportsStreaming = SupportsStreaming::Unknown;
 	for (const auto &attribute : attributes) {
 		attribute.match([&](const MTPDdocumentAttributeImageSize & data) {
 			dimensions = QSize(data.vw.v, data.vh.v);
@@ -474,7 +471,7 @@ void DocumentData::setattributes(
 					: VideoDocument;
 			}
 			_duration = data.vduration.v;
-			_supportsStreaming = data.is_supports_streaming();
+			setMaybeSupportsStreaming(data.is_supports_streaming());
 			dimensions = QSize(data.vw.v, data.vh.v);
 		}, [&](const MTPDdocumentAttributeAudio & data) {
 			if (type == FileDocument) {
@@ -531,6 +528,11 @@ void DocumentData::setattributes(
 		}
 	}
 	validateGoodThumbnail();
+	if (isAudioFile()
+		|| (isAnimation() && !isVideoMessage())
+		|| isVoiceMessage()) {
+		setMaybeSupportsStreaming(true);
+	}
 }
 
 bool DocumentData::checkWallPaperProperties() {
@@ -1192,16 +1194,15 @@ bool DocumentData::hasRemoteLocation() const {
 }
 
 bool DocumentData::canBeStreamed() const {
-	return hasRemoteLocation()
-		&& (isAudioFile()
-			|| ((isAnimation() || isVideoFile()) && supportsStreaming()));
+	return hasRemoteLocation() && supportsStreaming();
 }
 
 bool DocumentData::canBePlayed() const {
-	return (isAnimation()
-		|| isVideoFile()
-		|| isAudioFile()
-		|| isVoiceMessage())
+	return !_inappPlaybackFailed
+		&& (isAnimation()
+			|| isVideoFile()
+			|| isAudioFile()
+			|| isVoiceMessage())
 		&& (loaded() || canBeStreamed());
 }
 
@@ -1405,7 +1406,20 @@ bool DocumentData::isImage() const {
 }
 
 bool DocumentData::supportsStreaming() const {
-	return _supportsStreaming;
+	return (_supportsStreaming == SupportsStreaming::MaybeYes);
+}
+
+void DocumentData::setNotSupportsStreaming() {
+	_supportsStreaming = SupportsStreaming::No;
+}
+
+void DocumentData::setMaybeSupportsStreaming(bool supports) {
+	if (_supportsStreaming == SupportsStreaming::No) {
+		return;
+	}
+	_supportsStreaming = supports
+		? SupportsStreaming::MaybeYes
+		: SupportsStreaming::MaybeNo;
 }
 
 void DocumentData::recountIsImage() {
@@ -1587,28 +1601,30 @@ base::binary_guard ReadImageAsync(
 	return std::move(right);
 }
 
-void HandleUnsupportedMedia(
-		not_null<DocumentData*> document,
-		FullMsgId contextId) {
-	document->setInappPlaybackFailed();
-	const auto filepath = document->filepath(
-		DocumentData::FilePathResolveSaveFromData);
-	if (filepath.isEmpty()) {
-		const auto save = [=] {
-			Ui::hideLayer();
-			DocumentSaveClickHandler::Save(
-				(contextId ? contextId : Data::FileOrigin()),
-				document,
-				App::histItemById(contextId));
-		};
-		Ui::show(Box<ConfirmBox>(
-			lang(lng_player_cant_play),
-			lang(lng_player_download),
-			lang(lng_cancel),
-			save));
-	} else if (IsValidMediaFile(filepath)) {
-		File::Launch(filepath);
-	}
-}
+//void HandleUnsupportedMedia(
+//		not_null<DocumentData*> document,
+//		FullMsgId contextId) {
+//	using Error = ::Media::Streaming::Error;
+//
+//	document->setInappPlaybackFailed();
+//	const auto filepath = document->filepath(
+//		DocumentData::FilePathResolveSaveFromData);
+//	if (filepath.isEmpty()) {
+//		const auto save = [=] {
+//			Ui::hideLayer();
+//			DocumentSaveClickHandler::Save(
+//				(contextId ? contextId : Data::FileOrigin()),
+//				document,
+//				App::histItemById(contextId));
+//		};
+//		Ui::show(Box<ConfirmBox>(
+//			lang(lng_player_cant_stream),
+//			lang(lng_player_download),
+//			lang(lng_cancel),
+//			save));
+//	} else if (IsValidMediaFile(filepath)) {
+//		File::Launch(filepath);
+//	}
+//}
 
 } // namespace Data
diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h
index 2c284bfc9..fe6093047 100644
--- a/Telegram/SourceFiles/data/data_document.h
+++ b/Telegram/SourceFiles/data/data_document.h
@@ -167,6 +167,7 @@ public:
 	[[nodiscard]] bool isImage() const;
 	void recountIsImage();
 	[[nodiscard]] bool supportsStreaming() const;
+	void setNotSupportsStreaming();
 	void setData(const QByteArray &data) {
 		_data = data;
 	}
@@ -244,10 +245,17 @@ public:
 	std::unique_ptr<Data::UploadState> uploadingData;
 
 private:
+	enum class SupportsStreaming : uchar {
+		Unknown,
+		MaybeYes,
+		MaybeNo,
+		No,
+	};
 	friend class Serialize::Document;
 
 	LocationType locationType() const;
 	void validateGoodThumbnail();
+	void setMaybeSupportsStreaming(bool supports);
 
 	void destroyLoader(mtpFileLoader *newValue = nullptr) const;
 
@@ -274,7 +282,7 @@ private:
 	std::unique_ptr<DocumentAdditionalData> _additional;
 	int32 _duration = -1;
 	bool _isImage = false;
-	bool _supportsStreaming = false;
+	SupportsStreaming _supportsStreaming = SupportsStreaming::Unknown;
 	bool _inappPlaybackFailed = false;
 
 	ActionOnLoad _actionOnLoad = ActionOnLoadNone;
@@ -397,8 +405,4 @@ base::binary_guard ReadImageAsync(
 	FnMut<QImage(QImage)> postprocess,
 	FnMut<void(QImage&&)> done);
 
-void HandleUnsupportedMedia(
-	not_null<DocumentData*> document,
-	FullMsgId contextId);
-
 } // namespace Data
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index db1d3f681..c577d8013 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -1177,7 +1177,6 @@ void MainWidget::handleAudioUpdate(const Media::Player::TrackState &state) {
 	if (!Media::Player::IsStoppedOrStopping(state.state)) {
 		createPlayer();
 	} else if (state.state == State::StoppedAtStart) {
-		Data::HandleUnsupportedMedia(document, state.id.contextId());
 		closeBothPlayers();
 	}
 
diff --git a/Telegram/SourceFiles/media/player/media_player_instance.cpp b/Telegram/SourceFiles/media/player/media_player_instance.cpp
index 59ffa5a05..5ba7a8a2b 100644
--- a/Telegram/SourceFiles/media/player/media_player_instance.cpp
+++ b/Telegram/SourceFiles/media/player/media_player_instance.cpp
@@ -134,19 +134,18 @@ void Instance::setCurrent(const AudioMsgId &audioId) {
 		if (data->current == audioId) {
 			return;
 		}
-		const auto trackChanged = (data->current.audio() != audioId.audio())
-			|| (data->current.contextId() != audioId.contextId());
+		const auto changed = [&](const AudioMsgId & check) {
+			return (check.audio() != audioId.audio())
+				|| (check.contextId() != audioId.contextId());
+		};
+		const auto trackChanged = changed(data->current);
+		if (trackChanged && data->streamed && changed(data->streamed->id)) {
+			clearStreamed(data);
+		}
 		data->current = audioId;
 		if (!trackChanged) {
 			return;
 		}
-		const auto streamedId = data->streamed
-			? data->streamed->id
-			: AudioMsgId();
-		if (streamedId.audio() != audioId.audio()
-			|| streamedId.contextId() != audioId.contextId()) {
-			data->streamed = nullptr;
-		}
 		data->current = audioId;
 		data->isPlaying = false;
 
@@ -165,6 +164,16 @@ void Instance::setCurrent(const AudioMsgId &audioId) {
 	}
 }
 
+void Instance::clearStreamed(not_null<Data*> data) {
+	if (!data->streamed) {
+		return;
+	}
+	data->streamed->player.stop();
+	data->isPlaying = false;
+	emitUpdate(data->type);
+	data->streamed = nullptr;
+}
+
 void Instance::refreshPlaylist(not_null<Data*> data) {
 	if (!validPlaylist(data)) {
 		validatePlaylist(data);
@@ -386,6 +395,9 @@ void Instance::playStreamed(
 
 	const auto data = getData(audioId.type());
 	Assert(data != nullptr);
+	if (data->streamed) {
+		clearStreamed(data);
+	}
 	data->streamed = std::make_unique<Streamed>(
 		audioId,
 		&audioId.audio()->owner(),
@@ -607,38 +619,10 @@ void Instance::emitUpdate(AudioMsgId::Type type, CheckCallback check) {
 				_tracksFinishedNotifier.notify(type);
 			}
 		}
-		auto isPlaying = !IsStopped(state.state);
-		if (data->isPlaying != isPlaying) {
-			data->isPlaying = isPlaying;
-			if (data->isPlaying) {
-				preloadNext(data);
-			}
-		}
+		data->isPlaying = !IsStopped(state.state);
 	}
 }
 
-void Instance::preloadNext(not_null<Data*> data) {
-	//if (!data->current || !data->playlistSlice || !data->playlistIndex) {
-	//	return;
-	//}
-	//const auto nextIndex = *data->playlistIndex + 1;
-	//if (const auto item = itemByIndex(data, nextIndex)) {
-	//	if (const auto media = item->media()) {
-	//		if (const auto document = media->document()) {
-	//			const auto isLoaded = document->loaded(
-	//				DocumentData::FilePathResolveSaveFromDataSilent);
-	//			if (!isLoaded) {
-	//				DocumentOpenClickHandler::Open(
-	//					item->fullId(),
-	//					document,
-	//					item,
-	//					ActionOnLoadNone);
-	//			}
-	//		}
-	//	}
-	//}
-}
-
 void Instance::handleLogout() {
 	const auto reset = [&](AudioMsgId::Type type) {
 		const auto data = getData(type);
@@ -712,6 +696,23 @@ void Instance::handleStreamingUpdate(
 void Instance::handleStreamingError(
 		not_null<Data*> data,
 		Streaming::Error &&error) {
+	Expects(data->streamed != nullptr);
+
+	const auto document = data->streamed->id.audio();
+	const auto contextId = data->streamed->id.contextId();
+	if (error == Streaming::Error::NotStreamable) {
+		document->setNotSupportsStreaming();
+		DocumentSaveClickHandler::Save(
+			(contextId ? contextId : ::Data::FileOrigin()),
+			document,
+			App::histItemById(contextId));
+	} else if (error == Streaming::Error::OpenFailed) {
+		document->setInappPlaybackFailed();
+		DocumentSaveClickHandler::Save(
+			(contextId ? contextId : ::Data::FileOrigin()),
+			document,
+			App::histItemById(contextId));
+	}
 	emitUpdate(data->type);
 	if (data->streamed && data->streamed->player.failed()) {
 		data->streamed = nullptr;
diff --git a/Telegram/SourceFiles/media/player/media_player_instance.h b/Telegram/SourceFiles/media/player/media_player_instance.h
index 2f8b8e552..5b58da81c 100644
--- a/Telegram/SourceFiles/media/player/media_player_instance.h
+++ b/Telegram/SourceFiles/media/player/media_player_instance.h
@@ -19,7 +19,7 @@ namespace Streaming {
 class Loader;
 struct PlaybackOptions;
 struct Update;
-struct Error;
+enum class Error;
 } // namespace Streaming
 } // namespace Media
 
@@ -188,7 +188,6 @@ private:
 	void validatePlaylist(not_null<Data*> data);
 	void playlistUpdated(not_null<Data*> data);
 	bool moveInPlaylist(not_null<Data*> data, int delta, bool autonext);
-	void preloadNext(not_null<Data*> data);
 	HistoryItem *itemByIndex(not_null<Data*> data, int index);
 
 	void handleStreamingUpdate(
@@ -198,6 +197,7 @@ private:
 		not_null<Data*> data,
 		Streaming::Error &&error);
 
+	void clearStreamed(not_null<Data *> data);
 	void emitUpdate(AudioMsgId::Type type);
 	template <typename CheckCallback>
 	void emitUpdate(AudioMsgId::Type type, CheckCallback check);
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.cpp
index acb4b05fc..01ba767a4 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.cpp
@@ -20,7 +20,7 @@ AudioTrack::AudioTrack(
 	Stream &&stream,
 	AudioMsgId audioId,
 	FnMut<void(const Information &)> ready,
-	Fn<void()> error)
+	Fn<void(Error)> error)
 : _options(options)
 , _stream(std::move(stream))
 , _audioId(audioId)
@@ -51,7 +51,7 @@ void AudioTrack::process(Packet &&packet) {
 	if (initialized()) {
 		mixerEnqueue(std::move(packet));
 	} else if (!tryReadFirstFrame(std::move(packet))) {
-		_error();
+		_error(Error::InvalidData);
 	}
 }
 
@@ -188,7 +188,7 @@ rpl::producer<crl::time> AudioTrack::playPosition() {
 				return;
 			case State::StoppedAtError:
 			case State::StoppedAtStart:
-				_error();
+				_error(Error::InvalidData);
 				return;
 			case State::Starting:
 			case State::Playing:
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.h b/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.h
index b93007478..c6b45d28f 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_audio_track.h
@@ -21,7 +21,7 @@ public:
 		Stream &&stream,
 		AudioMsgId audioId,
 		FnMut<void(const Information &)> ready,
-		Fn<void()> error);
+		Fn<void(Error)> error);
 
 	// Called from the main thread.
 	// Must be called after 'ready' was invoked.
@@ -69,7 +69,7 @@ private:
 
 	// Assumed to be thread-safe.
 	FnMut<void(const Information &)> _ready;
-	const Fn<void()> _error;
+	const Fn<void(Error)> _error;
 
 	// First set from the same unspecified thread before _ready is called.
 	// After that is immutable.
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_common.h b/Telegram/SourceFiles/media/streaming/media_streaming_common.h
index 0bc7e448d..50baea6d5 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_common.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_common.h
@@ -100,7 +100,11 @@ struct Update {
 		Finished> data;
 };
 
-struct Error {
+enum class Error {
+	OpenFailed,
+	LoadFailed,
+	InvalidData,
+	NotStreamable,
 };
 
 struct FrameRequest {
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp
index 6048ba3cc..6bbd561e6 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp
@@ -44,8 +44,8 @@ int File::Context::read(bytes::span buffer) {
 		_semaphore.acquire();
 		if (_interrupted) {
 			return -1;
-		} else if (_reader->failed()) {
-			fail();
+		} else if (const auto error = _reader->failed()) {
+			fail(*error);
 			return -1;
 		}
 	}
@@ -84,21 +84,23 @@ void File::Context::logError(QLatin1String method, AvErrorWrap error) {
 void File::Context::logFatal(QLatin1String method) {
 	if (!unroll()) {
 		LogError(method);
-		fail();
+		fail(_format ? Error::InvalidData : Error::OpenFailed);
 	}
 }
 
 void File::Context::logFatal(QLatin1String method, AvErrorWrap error) {
 	if (!unroll()) {
 		LogError(method, error);
-		fail();
+		fail(_format ? Error::InvalidData : Error::OpenFailed);
 	}
 }
 
-Stream File::Context::initStream(AVMediaType type) {
+Stream File::Context::initStream(
+		not_null<AVFormatContext*> format,
+		AVMediaType type) {
 	auto result = Stream();
 	const auto index = result.index = av_find_best_stream(
-		_format.get(),
+		format,
 		type,
 		-1,
 		-1,
@@ -108,7 +110,7 @@ Stream File::Context::initStream(AVMediaType type) {
 		return {};
 	}
 
-	const auto info = _format->streams[index];
+	const auto info = format->streams[index];
 	if (type == AVMEDIA_TYPE_VIDEO) {
 		result.rotation = ReadRotationFromMetadata(info);
 		result.aspect = ValidateAspectRatio(info->sample_aspect_ratio);
@@ -131,7 +133,7 @@ Stream File::Context::initStream(AVMediaType type) {
 	result.timeBase = info->time_base;
 	result.duration = (info->duration != AV_NOPTS_VALUE)
 		? PtsToTime(info->duration, result.timeBase)
-		: PtsToTime(_format->duration, kUniversalTimeBase);
+		: PtsToTime(format->duration, kUniversalTimeBase);
 	if (result.duration == kTimeUnknown || !result.duration) {
 		return {};
 	}
@@ -142,6 +144,7 @@ Stream File::Context::initStream(AVMediaType type) {
 }
 
 void File::Context::seekToPosition(
+		not_null<AVFormatContext*> format,
 		const Stream &stream,
 		crl::time position) {
 	auto error = AvErrorWrap();
@@ -155,7 +158,7 @@ void File::Context::seekToPosition(
 	//
 	//const auto seekFlags = 0;
 	//error = av_seek_frame(
-	//	_format,
+	//	format,
 	//	streamIndex,
 	//	TimeToPts(position, kUniversalTimeBase),
 	//	seekFlags);
@@ -164,7 +167,7 @@ void File::Context::seekToPosition(
 	//}
 	//
 	error = av_seek_frame(
-		_format.get(),
+		format,
 		stream.index,
 		TimeToPts(
 			std::clamp(position, crl::time(0), stream.duration - 1),
@@ -197,43 +200,41 @@ void File::Context::start(crl::time position) {
 	if (unroll()) {
 		return;
 	}
-	_format = MakeFormatPointer(
+	auto format = MakeFormatPointer(
 		static_cast<void *>(this),
 		&Context::Read,
 		nullptr,
 		&Context::Seek);
-	if (!_format) {
-		return fail();
+	if (!format) {
+		return fail(Error::OpenFailed);
 	}
 
-	if ((error = avformat_find_stream_info(_format.get(), nullptr))) {
+	if ((error = avformat_find_stream_info(format.get(), nullptr))) {
 		return logFatal(qstr("avformat_find_stream_info"), error);
 	}
 
-	auto video = initStream(AVMEDIA_TYPE_VIDEO);
+	auto video = initStream(format.get(), AVMEDIA_TYPE_VIDEO);
 	if (unroll()) {
 		return;
 	}
 
-	auto audio = initStream(AVMEDIA_TYPE_AUDIO);
+	auto audio = initStream(format.get(), AVMEDIA_TYPE_AUDIO);
 	if (unroll()) {
 		return;
 	}
 
 	_reader->headerDone();
-	_totalDuration = std::max(
-		video.codec ? video.duration : kTimeUnknown,
-		audio.codec ? audio.duration : kTimeUnknown);
 	if (video.codec || audio.codec) {
-		seekToPosition(video.codec ? video : audio, position);
+		seekToPosition(format.get(), video.codec ? video : audio, position);
 	}
 	if (unroll()) {
 		return;
 	}
 
 	if (!_delegate->fileReady(std::move(video), std::move(audio))) {
-		return fail();
+		return fail(Error::OpenFailed);
 	}
+	_format = std::move(format);
 }
 
 void File::Context::readNextPacket() {
@@ -293,15 +294,14 @@ bool File::Context::unroll() const {
 	return failed() || interrupted();
 }
 
-void File::Context::fail() {
+void File::Context::fail(Error error) {
 	_failed = true;
-	_delegate->fileError();
+	_delegate->fileError(error);
 }
 
 File::Context::~Context() = default;
 
 bool File::Context::finished() const {
-	// #TODO streaming later looping
 	return unroll() || _readTillEnd;
 }
 
@@ -338,6 +338,10 @@ void File::stop() {
 	_context.reset();
 }
 
+bool File::isRemoteLoader() const {
+	return _reader.isRemoteLoader();
+}
+
 File::~File() {
 	stop();
 }
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_file.h b/Telegram/SourceFiles/media/streaming/media_streaming_file.h
index 20f5b3a5d..38a4c687e 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_file.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_file.h
@@ -36,6 +36,8 @@ public:
 	void wake();
 	void stop();
 
+	[[nodiscard]] bool isRemoteLoader() const;
+
 	~File();
 
 private:
@@ -66,10 +68,15 @@ private:
 		void logError(QLatin1String method, AvErrorWrap error);
 		void logFatal(QLatin1String method);
 		void logFatal(QLatin1String method, AvErrorWrap error);
-		void fail();
+		void fail(Error error);
 
-		Stream initStream(AVMediaType type);
-		void seekToPosition(const Stream &stream, crl::time position);
+		Stream initStream(
+			not_null<AVFormatContext *> format,
+			AVMediaType type);
+		void seekToPosition(
+			not_null<AVFormatContext *> format,
+			const Stream &stream,
+			crl::time position);
 
 		// TODO base::expected.
 		[[nodiscard]] base::variant<Packet, AvErrorWrap> readPacket();
@@ -88,7 +95,6 @@ private:
 		std::atomic<bool> _interrupted = false;
 
 		FormatPointer _format;
-		crl::time _totalDuration = kTimeUnknown;
 
 	};
 
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_file_delegate.h b/Telegram/SourceFiles/media/streaming/media_streaming_file_delegate.h
index 9eccbc29b..475846127 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_file_delegate.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_file_delegate.h
@@ -12,13 +12,14 @@ namespace Streaming {
 
 struct Stream;
 class Packet;
+enum class Error;
 
 class FileDelegate {
 public:
 	[[nodiscard]] virtual bool fileReady(
 		Stream &&video,
 		Stream &&audio) = 0;
-	virtual void fileError() = 0;
+	virtual void fileError(Error error) = 0;
 	virtual void fileWaitingForData() = 0;
 
 	// Return true if reading and processing more packets is desired.
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
index d62350726..7d2891d8d 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp
@@ -19,7 +19,8 @@ namespace Streaming {
 namespace {
 
 constexpr auto kBufferFor = 3 * crl::time(1000);
-constexpr auto kLoadInAdvanceFor = 64 * crl::time(1000);
+constexpr auto kLoadInAdvanceForRemote = 64 * crl::time(1000);
+constexpr auto kLoadInAdvanceForLocal = 5 * crl::time(1000);
 constexpr auto kMsFrequency = 1000; // 1000 ms per second.
 
 // If we played for 3 seconds and got stuck it looks like we're loading
@@ -79,6 +80,7 @@ Player::Player(
 	not_null<Data::Session*> owner,
 	std::unique_ptr<Loader> loader)
 : _file(std::make_unique<File>(owner, std::move(loader)))
+, _remoteLoader(_file->isRemoteLoader())
 , _renderFrameTimer([=] { checkNextFrame(); }) {
 }
 
@@ -123,7 +125,7 @@ void Player::trackReceivedTill(
 		state.receivedTill = position;
 	}
 	if (!_pauseReading
-		&& bothReceivedEnough(kLoadInAdvanceFor)
+		&& bothReceivedEnough(loadInAdvanceFor())
 		&& !receivedTillEnd()) {
 		_pauseReading = true;
 	}
@@ -145,7 +147,7 @@ void Player::trackPlayedTill(
 		_updates.fire({ PlaybackUpdate<Track>{ value } });
 	}
 	if (_pauseReading
-		&& (!bothReceivedEnough(kLoadInAdvanceFor) || receivedTillEnd())) {
+		&& (!bothReceivedEnough(loadInAdvanceFor()) || receivedTillEnd())) {
 		_pauseReading = false;
 		_file->wake();
 		++wakes;
@@ -204,10 +206,10 @@ bool Player::fileReady(Stream &&video, Stream &&audio) {
 		});
 	};
 	const auto error = [&](auto &stream) {
-		return [=, &stream] {
+		return [=, &stream](Error error) {
 			crl::on_main(weak, [=, &stream] {
 				stream = nullptr;
-				streamFailed();
+				streamFailed(error);
 			});
 		};
 	};
@@ -253,11 +255,11 @@ bool Player::fileReady(Stream &&video, Stream &&audio) {
 	return true;
 }
 
-void Player::fileError() {
+void Player::fileError(Error error) {
 	_waitingForData = false;
 
 	crl::on_main(&_sessionGuard, [=] {
-		fail();
+		fail(error);
 	});
 }
 
@@ -331,11 +333,11 @@ void Player::streamReady(Information &&information) {
 	provideStartInformation();
 }
 
-void Player::streamFailed() {
+void Player::streamFailed(Error error) {
 	if (_stage == Stage::Initializing) {
 		provideStartInformation();
 	} else {
-		fail();
+		fail(error);
 	}
 }
 
@@ -348,7 +350,7 @@ void Player::provideStartInformation() {
 	} else if ((!_audio && !_video)
 		|| (!_audio && _options.mode == Mode::Audio)
 		|| (!_video && _options.mode == Mode::Video)) {
-		fail();
+		fail(Error::OpenFailed);
 	} else {
 		_stage = Stage::Ready;
 
@@ -365,11 +367,11 @@ void Player::provideStartInformation() {
 	}
 }
 
-void Player::fail() {
+void Player::fail(Error error) {
 	_sessionLifetime = rpl::lifetime();
 	const auto stopGuarded = crl::guard(&_sessionGuard, [=] { stop(); });
-	_lastFailureStage = _stage;
-	_updates.fire_error({});
+	_lastFailure = error;
+	_updates.fire_error(std::move(error));
 	stopGuarded();
 }
 
@@ -382,7 +384,7 @@ void Player::play(const PlaybackOptions &options) {
 	const auto previous = getCurrentReceivedTill();
 
 	stop();
-	_lastFailureStage = Stage::Uninitialized;
+	_lastFailure = std::nullopt;
 
 	savePreviousReceivedTill(options, previous);
 	_options = options;
@@ -404,6 +406,10 @@ void Player::savePreviousReceivedTill(
 		: kTimeUnknown;
 }
 
+crl::time Player::loadInAdvanceFor() const {
+	return _remoteLoader ? kLoadInAdvanceForRemote : kLoadInAdvanceForLocal;
+}
+
 void Player::pause() {
 	Expects(active());
 
@@ -560,8 +566,8 @@ void Player::stop() {
 	_information = Information();
 }
 
-bool Player::failed() const {
-	return (_lastFailureStage != Stage::Uninitialized);
+std::optional<Error> Player::failed() const {
+	return _lastFailure;
 }
 
 bool Player::playing() const {
@@ -626,10 +632,11 @@ Media::Player::TrackState Player::prepareLegacyState() const {
 
 	auto result = Media::Player::TrackState();
 	result.id = _audioId.externalPlayId() ? _audioId : _options.audioId;
-	result.state = (_lastFailureStage == Stage::Started)
-		? State::StoppedAtError
-		: failed()
+	result.state = (_lastFailure == Error::OpenFailed
+		|| _lastFailure == Error::NotStreamable)
 		? State::StoppedAtStart
+		: _lastFailure
+		? State::StoppedAtError
 		: finished()
 		? State::StoppedAtEnd
 		: paused()
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.h b/Telegram/SourceFiles/media/streaming/media_streaming_player.h
index 02f4ffae2..8981ea06a 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_player.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.h
@@ -53,7 +53,7 @@ public:
 	[[nodiscard]] bool playing() const;
 	[[nodiscard]] bool buffering() const;
 	[[nodiscard]] bool paused() const;
-	[[nodiscard]] bool failed() const;
+	[[nodiscard]] std::optional<Error> failed() const;
 	[[nodiscard]] bool finished() const;
 
 	[[nodiscard]] rpl::producer<Update, Error> updates() const;
@@ -80,17 +80,17 @@ private:
 
 	// FileDelegate methods are called only from the File thread.
 	bool fileReady(Stream &&video, Stream &&audio) override;
-	void fileError() override;
+	void fileError(Error error) override;
 	void fileWaitingForData() override;
 	bool fileProcessPacket(Packet &&packet) override;
 	bool fileReadMore() override;
 
 	// Called from the main thread.
 	void streamReady(Information &&information);
-	void streamFailed();
+	void streamFailed(Error error);
 	void start();
 	void provideStartInformation();
-	void fail();
+	void fail(Error error);
 	void checkNextFrame();
 	void renderFrame(crl::time now);
 	void audioReceivedTill(crl::time position);
@@ -109,6 +109,7 @@ private:
 	void savePreviousReceivedTill(
 		const PlaybackOptions &options,
 		crl::time previousReceivedTill);
+	[[nodiscard]] crl::time loadInAdvanceFor() const;
 
 	template <typename Track>
 	void trackReceivedTill(
@@ -150,12 +151,13 @@ private:
 	// Belongs to the main thread.
 	Information _information;
 	Stage _stage = Stage::Uninitialized;
-	Stage _lastFailureStage = Stage::Uninitialized;
+	std::optional<Error> _lastFailure;
 	bool _pausedByUser = false;
 	bool _pausedByWaitingForData = false;
 	bool _paused = false;
 	bool _audioFinished = false;
 	bool _videoFinished = false;
+	bool _remoteLoader = false;
 
 	crl::time _startedTime = kTimeUnknown;
 	crl::time _pausedTime = kTimeUnknown;
@@ -163,7 +165,7 @@ private:
 	base::Timer _renderFrameTimer;
 	rpl::event_stream<Update, Error> _updates;
 
-	crl::time _totalDuration = 0;
+	crl::time _totalDuration = kTimeUnknown;
 	crl::time _loopingShift = 0;
 	crl::time _previousReceivedTill = kTimeUnknown;
 
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp
index 3ce075bf9..b8b8bc6fa 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 */
 #include "media/streaming/media_streaming_reader.h"
 
+#include "media/streaming/media_streaming_common.h"
 #include "media/streaming/media_streaming_loader.h"
 #include "storage/cache/storage_cache_database.h"
 #include "data/data_session.h"
@@ -18,11 +19,14 @@ namespace {
 constexpr auto kPartSize = Loader::kPartSize;
 constexpr auto kPartsInSlice = 64;
 constexpr auto kInSlice = kPartsInSlice * kPartSize;
-constexpr auto kMaxPartsInHeader = 72;
-constexpr auto kMaxInHeader = kMaxPartsInHeader * kPartSize;
+constexpr auto kMaxPartsInHeader = 16;
 constexpr auto kMaxOnlyInHeader = 80 * kPartSize;
 constexpr auto kSlicesInMemory = 2;
 
+// 1 MB of header parts can be outside the first slice for us to still
+// put the whole first slice of the file in the header cache entry.
+//constexpr auto kMaxOutsideHeaderPartsForOptimizedMode = 8;
+
 // 1 MB of parts are requested from cloud ahead of reading demand.
 constexpr auto kPreloadPartsAhead = 8;
 
@@ -286,6 +290,11 @@ void Reader::Slices::headerDone(bool fromCache) {
 	}
 }
 
+bool Reader::Slices::headerWontBeFilled() const {
+	return (_headerMode == HeaderMode::Unknown)
+		&& (_header.parts.size() == kMaxPartsInHeader);
+}
+
 void Reader::Slices::applyHeaderCacheData() {
 	if (_header.parts.empty()) {
 		return;
@@ -318,21 +327,21 @@ bool Reader::Slices::processCacheResult(
 	return success;
 }
 
-bool Reader::Slices::processPart(int offset, QByteArray &&bytes) {
+std::optional<Error> Reader::Slices::processPart(
+		int offset,
+		QByteArray &&bytes) {
 	Expects(offset / kInSlice < _data.size());
 
 	const auto index = offset / kInSlice;
 	if (_headerMode == HeaderMode::Unknown) {
 		if (_header.parts.contains(offset)) {
-			return true;
-		} else if (_header.parts.size() == kMaxPartsInHeader) {
-			// #TODO streaming later unavailable, full load?
-			return false;
+			return {};
+		} else if (_header.parts.size() < kMaxPartsInHeader) {
+			_header.addPart(offset, bytes);
 		}
-		_header.addPart(offset, bytes);
 	}
 	_data[index].addPart(offset - index * kInSlice, std::move(bytes));
-	return true;
+	return {};
 }
 
 auto Reader::Slices::fill(int offset, bytes::span buffer) -> FillResult {
@@ -544,6 +553,10 @@ void Reader::stop() {
 	_waiting = nullptr;
 }
 
+bool Reader::isRemoteLoader() const {
+	return _loader->baseCacheKey().has_value();
+}
+
 std::shared_ptr<Reader::CacheHelper> Reader::InitCacheHelper(
 		std::optional<Storage::Cache::Key> baseKey) {
 	if (!baseKey) {
@@ -584,7 +597,7 @@ int Reader::size() const {
 	return _loader->size();
 }
 
-bool Reader::failed() const {
+std::optional<Error> Reader::failed() const {
 	return _failed;
 }
 
@@ -652,6 +665,10 @@ bool Reader::fillFromSlices(int offset, bytes::span buffer) {
 	using namespace rpl::mappers;
 
 	auto result = _slices.fill(offset, buffer);
+	if (!result.filled && _slices.headerWontBeFilled()) {
+		_failed = Error::NotStreamable;
+		return false;
+	}
 
 	for (const auto sliceNumber : result.sliceNumbersFromCache.values()) {
 		readFromCache(sliceNumber);
@@ -724,14 +741,16 @@ bool Reader::processLoadedParts() {
 		if (part.offset == LoadedPart::kFailedOffset
 			|| (part.bytes.size() != Loader::kPartSize
 				&& part.offset + part.bytes.size() != size())) {
-			_failed = true;
+			_failed = Error::LoadFailed;
 			return false;
 		} else if (!_loadingOffsets.remove(part.offset)) {
 			continue;
-		} else if (!_slices.processPart(
-				part.offset,
-				std::move(part.bytes))) {
-			_failed = true;
+		}
+		const auto error = _slices.processPart(
+			part.offset,
+			std::move(part.bytes));
+		if (error) {
+			_failed = *error;
 			return false;
 		}
 	}
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_reader.h b/Telegram/SourceFiles/media/streaming/media_streaming_reader.h
index b37e59d06..c71cca8dd 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_reader.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_reader.h
@@ -25,22 +25,25 @@ namespace Streaming {
 
 class Loader;
 struct LoadedPart;
+enum class Error;
 
 class Reader final {
 public:
 	Reader(not_null<Data::Session*> owner, std::unique_ptr<Loader> loader);
 
-	int size() const;
-	bool fill(
+	[[nodiscard]] int size() const;
+	[[nodiscard]] bool fill(
 		int offset,
 		bytes::span buffer,
 		not_null<crl::semaphore*> notify);
-	bool failed() const;
+	[[nodiscard]] std::optional<Error> failed() const;
 
 	void headerDone();
 
 	void stop();
 
+	[[nodiscard]] bool isRemoteLoader() const;
+
 	~Reader();
 
 private:
@@ -111,9 +114,10 @@ private:
 		Slices(int size, bool useCache);
 
 		void headerDone(bool fromCache);
+		bool headerWontBeFilled() const;
 
 		bool processCacheResult(int sliceNumber, QByteArray &&result);
-		bool processPart(int offset, QByteArray &&bytes);
+		std::optional<Error> processPart(int offset, QByteArray &&bytes);
 
 		FillResult fill(int offset, bytes::span buffer);
 		SerializedSlice unloadToCache();
@@ -167,7 +171,7 @@ private:
 	PriorityQueue _loadingOffsets;
 
 	Slices _slices;
-	bool _failed = false;
+	std::optional<Error> _failed;
 	rpl::lifetime _lifetime;
 
 };
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_video_track.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_video_track.cpp
index fdfa68247..7abd1c349 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_video_track.cpp
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_video_track.cpp
@@ -31,7 +31,7 @@ public:
 		Stream &&stream,
 		const AudioMsgId &audioId,
 		FnMut<void(const Information &)> ready,
-		Fn<void()> error);
+		Fn<void(Error)> error);
 
 	void process(Packet &&packet);
 
@@ -80,7 +80,7 @@ private:
 	AudioMsgId _audioId;
 	bool _noMoreData = false;
 	FnMut<void(const Information &)> _ready;
-	Fn<void()> _error;
+	Fn<void(Error)> _error;
 	crl::time _pausedTime = kTimeUnknown;
 	crl::time _resumedTime = kTimeUnknown;
 	mutable TimePoint _syncTimePoint;
@@ -103,7 +103,7 @@ VideoTrackObject::VideoTrackObject(
 	Stream &&stream,
 	const AudioMsgId &audioId,
 	FnMut<void(const Information &)> ready,
-	Fn<void()> error)
+	Fn<void(Error)> error)
 : _weak(std::move(weak))
 , _options(options)
 , _shared(shared)
@@ -141,7 +141,7 @@ void VideoTrackObject::process(Packet &&packet) {
 		_stream.queue.push_back(std::move(packet));
 		queueReadFrames();
 	} else if (!tryReadFirstFrame(std::move(packet))) {
-		_error();
+		_error(Error::InvalidData);
 	}
 }
 
@@ -209,7 +209,7 @@ auto VideoTrackObject::readFrame(not_null<Frame*> frame) -> FrameResult {
 			}
 		} else if (error.code() != AVERROR(EAGAIN) || _noMoreData) {
 			interrupt();
-			_error();
+			_error(Error::InvalidData);
 			return FrameResult::Error;
 		}
 		Assert(_stream.queue.empty());
@@ -220,7 +220,7 @@ auto VideoTrackObject::readFrame(not_null<Frame*> frame) -> FrameResult {
 	LOG(("GOT FRAME: %1 (queue %2)").arg(position).arg(_stream.queue.size()));
 	if (position == kTimeUnknown) {
 		interrupt();
-		_error();
+		_error(Error::InvalidData);
 		return FrameResult::Error;
 	}
 	std::swap(frame->decoded, _stream.frame);
@@ -244,7 +244,7 @@ void VideoTrackObject::presentFrameIfNeeded() {
 		if (frame->original.isNull()) {
 			frame->prepared = QImage();
 			interrupt();
-			_error();
+			_error(Error::InvalidData);
 			return;
 		}
 
@@ -581,7 +581,7 @@ VideoTrack::VideoTrack(
 	Stream &&stream,
 	const AudioMsgId &audioId,
 	FnMut<void(const Information &)> ready,
-	Fn<void()> error)
+	Fn<void(Error)> error)
 : _streamIndex(stream.index)
 , _streamTimeBase(stream.timeBase)
 , _streamDuration(stream.duration)
diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_video_track.h b/Telegram/SourceFiles/media/streaming/media_streaming_video_track.h
index f5215219e..637d235b1 100644
--- a/Telegram/SourceFiles/media/streaming/media_streaming_video_track.h
+++ b/Telegram/SourceFiles/media/streaming/media_streaming_video_track.h
@@ -25,7 +25,7 @@ public:
 		Stream &&stream,
 		const AudioMsgId &audioId,
 		FnMut<void(const Information &)> ready,
-		Fn<void()> error);
+		Fn<void(Error)> error);
 
 	// Thread-safe.
 	[[nodiscard]] int streamIndex() const;
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
index 48b40e8c8..3116bea97 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
@@ -163,6 +163,7 @@ struct OverlayWidget::Streamed {
 	base::Timer timer;
 
 	bool resumeOnCallEnd = false;
+	std::optional<Streaming::Error> lastError;
 };
 
 OverlayWidget::Streamed::Streamed(
@@ -327,7 +328,7 @@ bool OverlayWidget::videoIsGifv() const {
 QImage OverlayWidget::videoFrame() const {
 	Expects(videoShown());
 
-	auto request = Media::Streaming::FrameRequest();
+	auto request = Streaming::FrameRequest();
 	//request.radius = (_doc && _doc->isVideoMessage())
 	//	? ImageRoundRadius::Ellipse
 	//	: ImageRoundRadius::None;
@@ -893,7 +894,7 @@ void OverlayWidget::showSaveMsgFile() {
 
 void OverlayWidget::updateMixerVideoVolume() const {
 	if (_streamed) {
-		Media::Player::mixer()->setVideoVolume(Global::VideoVolume());
+		Player::mixer()->setVideoVolume(Global::VideoVolume());
 	}
 }
 
@@ -1514,19 +1515,19 @@ void OverlayWidget::refreshCaption(HistoryItem *item) {
 void OverlayWidget::refreshGroupThumbs() {
 	const auto existed = (_groupThumbs != nullptr);
 	if (_index && _sharedMediaData) {
-		Media::View::GroupThumbs::Refresh(
+		View::GroupThumbs::Refresh(
 			_groupThumbs,
 			*_sharedMediaData,
 			*_index,
 			_groupThumbsAvailableWidth);
 	} else if (_index && _userPhotosData) {
-		Media::View::GroupThumbs::Refresh(
+		View::GroupThumbs::Refresh(
 			_groupThumbs,
 			*_userPhotosData,
 			*_index,
 			_groupThumbsAvailableWidth);
 	} else if (_index && _collageData) {
-		Media::View::GroupThumbs::Refresh(
+		View::GroupThumbs::Refresh(
 			_groupThumbs,
 			{ _msgid, &*_collageData },
 			*_index,
@@ -1555,8 +1556,8 @@ void OverlayWidget::initGroupThumbs() {
 	}, _groupThumbs->lifetime());
 
 	_groupThumbs->activateRequests(
-	) | rpl::start_with_next([this](Media::View::GroupThumbs::Key key) {
-		using CollageKey = Media::View::GroupThumbs::CollageKey;
+	) | rpl::start_with_next([this](View::GroupThumbs::Key key) {
+		using CollageKey = View::GroupThumbs::CollageKey;
 		if (const auto photoId = base::get_if<PhotoId>(&key)) {
 			const auto photo = Auth().data().photo(*photoId);
 			moveToEntity({ photo, nullptr });
@@ -2027,7 +2028,7 @@ void OverlayWidget::handleStreamingUpdate(Streaming::Update &&update) {
 		playbackWaitingChange(update.waiting);
 	}, [&](MutedByOther) {
 	}, [&](Finished) {
-		const auto finishTrack = [](Media::Streaming::TrackState &state) {
+		const auto finishTrack = [](Streaming::TrackState &state) {
 			state.position = state.receivedTill = state.duration;
 		};
 		finishTrack(_streamed->info.audio.state);
@@ -2037,8 +2038,19 @@ void OverlayWidget::handleStreamingUpdate(Streaming::Update &&update) {
 }
 
 void OverlayWidget::handleStreamingError(Streaming::Error &&error) {
-	playbackWaitingChange(false);
-	updatePlaybackState();
+	if (error == Streaming::Error::NotStreamable) {
+		_doc->setNotSupportsStreaming();
+	} else if (error == Streaming::Error::OpenFailed) {
+		_doc->setInappPlaybackFailed();
+	}
+	if (!_doc->canBePlayed()) {
+		clearStreaming();
+		displayDocument(_doc, App::histItemById(_msgid));
+	} else {
+		_streamed->lastError = std::move(error);
+		playbackWaitingChange(false);
+		updatePlaybackState();
+	}
 }
 
 void OverlayWidget::playbackWaitingChange(bool waiting) {
@@ -2149,13 +2161,7 @@ void OverlayWidget::refreshClipControllerGeometry() {
 }
 
 void OverlayWidget::playbackControlsPlay() {
-	const auto legacy = _streamed->player.prepareLegacyState();
-	if (legacy.state == Player::State::StoppedAtStart) {
-		Data::HandleUnsupportedMedia(_doc, _msgid);
-		close();
-	} else {
-		playbackPauseResume();
-	}
+	playbackPauseResume();
 }
 
 void OverlayWidget::playbackControlsPause() {
@@ -2174,9 +2180,11 @@ void OverlayWidget::playbackPauseResume() {
 	Expects(_streamed != nullptr);
 
 	_streamed->resumeOnCallEnd = false;
+	_streamed->lastError = std::nullopt;
 	if (const auto item = App::histItemById(_msgid)) {
 		if (_streamed->player.failed()) {
-			displayDocument(_doc, item);
+			clearStreaming();
+			initStreaming();
 		} else if (_streamed->player.finished()) {
 			restartAtSeekPosition(0);
 		} else if (_streamed->player.paused()) {
@@ -2209,8 +2217,8 @@ void OverlayWidget::restartAtSeekPosition(crl::time position) {
 	}
 	_streamed->player.play(options);
 
-	Media::Player::instance()->pause(AudioMsgId::Type::Voice);
-	Media::Player::instance()->pause(AudioMsgId::Type::Song);
+	Player::instance()->pause(AudioMsgId::Type::Voice);
+	Player::instance()->pause(AudioMsgId::Type::Song);
 
 	_streamed->info.audio.state.position
 		= _streamed->info.video.state.position
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h
index c9bcd2afd..e56d87089 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h
@@ -39,7 +39,7 @@ struct TrackState;
 namespace Streaming {
 struct Information;
 struct Update;
-struct Error;
+enum class Error;
 } // namespace Streaming
 } // namespace Media