AVFoundation框架解析(二十一)—— 一個(gè)簡(jiǎn)單的視頻流預(yù)覽和播放示例之解析(一)

版本記錄

版本號(hào) 時(shí)間
V1.0 2018.10.01 星期一

前言

AVFoundation框架是ios中很重要的框架虏杰,所有與視頻音頻相關(guān)的軟硬件控制都在這個(gè)框架里面贱鼻,接下來(lái)這幾篇就主要對(duì)這個(gè)框架進(jìn)行介紹和講解喻奥。感興趣的可以看我上幾篇。
1. AVFoundation框架解析(一)—— 基本概覽
2. AVFoundation框架解析(二)—— 實(shí)現(xiàn)視頻預(yù)覽錄制保存到相冊(cè)
3. AVFoundation框架解析(三)—— 幾個(gè)關(guān)鍵問(wèn)題之關(guān)于框架的深度概括
4. AVFoundation框架解析(四)—— 幾個(gè)關(guān)鍵問(wèn)題之AVFoundation探索(一)
5. AVFoundation框架解析(五)—— 幾個(gè)關(guān)鍵問(wèn)題之AVFoundation探索(二)
6. AVFoundation框架解析(六)—— 視頻音頻的合成(一)
7. AVFoundation框架解析(七)—— 視頻組合和音頻混合調(diào)試
8. AVFoundation框架解析(八)—— 優(yōu)化用戶的播放體驗(yàn)
9. AVFoundation框架解析(九)—— AVFoundation的變化(一)
10. AVFoundation框架解析(十)—— AVFoundation的變化(二)
11. AVFoundation框架解析(十一)—— AVFoundation的變化(三)
12. AVFoundation框架解析(十二)—— AVFoundation的變化(四)
13. AVFoundation框架解析(十三)—— 構(gòu)建基本播放應(yīng)用程序
14. AVFoundation框架解析(十四)—— VAssetWriter和AVAssetReader的Timecode支持(一)
15. AVFoundation框架解析(十五)—— VAssetWriter和AVAssetReader的Timecode支持(二)
16. AVFoundation框架解析(十六)—— 一個(gè)簡(jiǎn)單示例之播放赖欣、錄制以及混合視頻(一)
17. AVFoundation框架解析(十七)—— 一個(gè)簡(jiǎn)單示例之播放屑彻、錄制以及混合視頻之源碼及效果展示(二)
18. AVFoundation框架解析(十八)—— AVAudioEngine之基本概覽(一)
19. AVFoundation框架解析(十九)—— AVAudioEngine之詳細(xì)說(shuō)明和一個(gè)簡(jiǎn)單示例(二)
20. AVFoundation框架解析(二十)—— AVAudioEngine之詳細(xì)說(shuō)明和一個(gè)簡(jiǎn)單示例源碼(三)

開(kāi)始

首先看一下寫作環(huán)境

Swift 4.2, iOS 12, Xcode 10

注意:如果您正在使用模擬器Build,請(qǐng)準(zhǔn)備好關(guān)閉斷點(diǎn)或大量點(diǎn)擊跳過(guò)按鈕顶吮。 如果您看到以AudioHAL_ClientCUICatalog開(kāi)頭的錯(cuò)誤或警告社牲,請(qǐng)隨意忽略它們并繼續(xù)。

在開(kāi)始時(shí)悴了,首先建立工程并配置可用資源搏恤,這里就不多說(shuō)了,然后湃交,打開(kāi)TravelVlogs.xcodeproj并前往VideoFeedViewController.swift熟空。


Introduction to AVKit - AVKit介紹

一個(gè)有用的開(kāi)發(fā)智慧:始終支持您可用的最高抽象級(jí)別。 然后搞莺,當(dāng)您使用的不再適合您的需求時(shí)息罗,您可以降低到較低等級(jí)的API。 根據(jù)這一建議才沧,您將在最高級(jí)別的視頻框架中開(kāi)始您的旅程阱当。

AVKit位于AVFoundation之上俏扩,提供與視頻交互所需的所有UI。

如果您構(gòu)建并運(yùn)行弊添,您將看到一個(gè)已經(jīng)設(shè)置了一個(gè)充滿潛在視頻的表的應(yīng)用程序录淡。

您的目標(biāo)是在用戶點(diǎn)擊其中一個(gè)單元格時(shí)顯示視頻播放器。

1. Adding Local Playback - 添加本地播放

實(shí)際上您可以播放兩種類型的視頻油坝。 你要看的第一個(gè)是當(dāng)前已經(jīng)存在于手機(jī)硬盤上的類型嫉戚。 稍后,您將學(xué)習(xí)如何播放從服務(wù)器流式傳輸?shù)囊曨l澈圈。

要開(kāi)始使用彬檀,請(qǐng)導(dǎo)航到VideoFeedViewController.swift。 在UIKit導(dǎo)入下方添加以下導(dǎo)入瞬女。

import AVKit

看下面這個(gè)窍帝,你會(huì)看到你已經(jīng)有一個(gè)tableViewVideos數(shù)組定義。 這就是現(xiàn)有tableView填充數(shù)據(jù)的方式诽偷。Videos本身來(lái)自視頻管理類坤学。 您可以查看AppDelegate.swift以了解它們是如何獲取的。

接下來(lái)报慕,向下滾動(dòng)深浮,直到找到tableView(_ tableView:didSelectRowAt :)。 將以下代碼添加到現(xiàn)有方法:

//1
let video = videos[indexPath.row]

//2
let videoURL = video.url
let player = AVPlayer(url: videoURL)
  • 1) 首先眠冈,您獲取視頻模型對(duì)象飞苇。
  • 2) 所有Video對(duì)象都有一個(gè)url屬性,表示視頻文件的路徑蜗顽。 在這里布卡,您獲取URL并創(chuàng)建一個(gè)AVPlayer對(duì)象。

AVPlayer是在iOS上播放視頻的核心雇盖。

播放器對(duì)象可以啟動(dòng)和停止視頻忿等,更改播放速率甚至可以上下調(diào)節(jié)音量。 您可以將播放器視為能夠一次管理一個(gè)媒體資源播放的控制器對(duì)象刊懈。

在方法結(jié)束時(shí)这弧,添加以下行以獲取視圖控制器設(shè)置娃闲。

let playerViewController = AVPlayerViewController()
playerViewController.player = player

present(playerViewController, animated: true) {
  player.play()
}

AVPlayerViewController是一個(gè)方便的視圖控制器虚汛,需要一個(gè)player對(duì)象才有用。 一旦有了它皇帮,就將它呈現(xiàn)為全屏視頻播放器卷哩。

演示動(dòng)畫完成后,您可以調(diào)用play()來(lái)啟動(dòng)視頻属拾。

這就是它的全部将谊! 構(gòu)建并運(yùn)行以查看其外觀冷溶。

視圖控制器顯示一組基本控件。 這包括一個(gè)播放器按鈕尊浓,一個(gè)靜音按鈕和15秒跳過(guò)按鈕來(lái)前進(jìn)和后退逞频。

2. Adding Remote Playback - 添加遠(yuǎn)程播放

這很簡(jiǎn)單。 如何從遠(yuǎn)程URL添加視頻播放栋齿? 當(dāng)然苗胀,這肯定要困難得多。

轉(zhuǎn)到AppDelegate.swift瓦堵。 找到feed.videos設(shè)置的行基协。 而不是加載本地視頻,通過(guò)用以下內(nèi)容替換該行來(lái)加載所有視頻菇用。

feed.videos = Video.allVideos()

就是這樣澜驮! 轉(zhuǎn)到Video.swift。 在這里你可以看到allVideos()只是加載一個(gè)額外的視頻惋鸥。 唯一的區(qū)別是它的url屬性表示W(wǎng)eb上的地址而不是文件路徑杂穷。

Build并運(yùn)行,然后滾動(dòng)到Feed的底部揩慕,找到キツネ村(kitsune-mura)Fox Village視頻亭畜。

這就是AVPlayerViewController的美感,你需要的只是一個(gè)URL迎卤,你很高興拴鸵!

實(shí)際上,轉(zhuǎn)到allVideos()并換掉這一行:

let videoURLString = 
  "https://wolverine.raywenderlich.com/content/ios/tutorials/video_streaming/foxVillage.mp4"

用下面這個(gè)

let videoURLString = 
  "https://wolverine.raywenderlich.com/content/ios/tutorials/video_streaming/foxVillage.m3u8"

Build并運(yùn)行蜗搔,你會(huì)看到fox village的視頻仍然有效劲藐。

唯一的區(qū)別是第二個(gè)URL代表HLS LivestreamHLS實(shí)時(shí)流式傳輸通過(guò)將視頻分成10秒塊來(lái)實(shí)現(xiàn)樟凄。 然后聘芜,這些服務(wù)一次被提供給客戶端。 正如您在示例GIF中看到的那樣缝龄,視頻開(kāi)始播放的速度比使用MP4版本時(shí)快得多汰现。


Adding a Looping Video Preview - 添加循環(huán)視頻預(yù)覽

您可能已經(jīng)注意到右下角的黑盒子。 你將把那個(gè)黑盒子變成一個(gè)浮動(dòng)的自定義視頻播放器叔壤。 它的目的是播放一組旋轉(zhuǎn)剪輯瞎饲,讓用戶對(duì)所有這些視頻感到興奮。

然后你需要添加一些自定義手勢(shì)炼绘,如點(diǎn)擊打開(kāi)聲音和雙擊以將其更改為2倍速度嗅战。 當(dāng)您想要對(duì)事物的工作方式進(jìn)行非常具體的控制時(shí),最好編寫自己的視頻視圖俺亮。

返回VideoFeedViewController.swift并查看屬性定義驮捍。 您將看到此類的shell已存在疟呐,并且正在使用一組視頻剪輯創(chuàng)建。


Introduction to AVFoundation - AVFoundation簡(jiǎn)介

雖然AVFoundation可能會(huì)讓人覺(jué)得有點(diǎn)嚇人东且,但是你所處理的大多數(shù)對(duì)象仍然是相當(dāng)高級(jí)的启具,所有事情都要考慮。

您需要熟悉的主要課程是:

  • 1) AVPlayerLayer:這個(gè)特殊的CALayer子類可以顯示給定AVPlayer對(duì)象的回放珊泳。
  • 2)AVAsset:這些是媒體資產(chǎn)的靜態(tài)表示富纸。 資產(chǎn)對(duì)象包含持續(xù)時(shí)間和創(chuàng)建日期等信息。
  • 3)AVPlayerItemAVAsset的動(dòng)態(tài)對(duì)應(yīng)對(duì)象旨椒。 此對(duì)象表示可播放視頻的當(dāng)前狀態(tài)晓褪。 這是您需要為AVPlayer提供的東西。

AVFoundation是一個(gè)巨大的框架综慎,遠(yuǎn)遠(yuǎn)超出這幾個(gè)類涣仿。 幸運(yùn)的是,這就是創(chuàng)建循環(huán)視頻播放器所需的全部?jī)?nèi)容示惊。

你將依次回到這些中好港,所以不要擔(dān)心記憶它們或任何東西。

1. Writing a Custom Video View with AVPlayerLayer - 使用AVPlayerLayer寫一個(gè)自定義視頻視圖

您需要考慮的第一個(gè)類是AVPlayerLayer米罚。 此CALayer子類與任何其他圖層類似:它在屏幕上顯示其contents屬性中的任何內(nèi)容钧汹。、

這個(gè)圖層恰好用你通過(guò)player屬性給出的視頻中的幀填充其內(nèi)容录择。

轉(zhuǎn)到VideoPlayerView.swift拔莱,您將在其中找到一個(gè)用于顯示視頻的空視圖。

您需要做的第一件事是添加正確的import語(yǔ)句隘竭,這次是AVFoundation塘秦。

import AVFoundation

現(xiàn)在你可以將AVPlayerLayer融入其中。

UIView實(shí)際上只是一個(gè)封裝CALayer的包裝器动看。 它提供了觸摸處理和可訪問(wèn)性功能尊剔,但不是子類。 相反菱皆,它擁有并管理底層layer屬性须误。 一個(gè)很好的技巧是你可以實(shí)際指定你希望視圖子類擁有哪種類型的層。

添加以下屬性覆蓋以通知此類它應(yīng)使用AVPlayerLayer而不是普通CALayer仇轻。

override class var layerClass: AnyClass {
  return AVPlayerLayer.self
}

由于您要在視圖中包裝player layer京痢,因此您需要暴露player屬性。

為此拯田,首先添加以下計(jì)算屬性历造,這樣您就不需要一直強(qiáng)制轉(zhuǎn)換圖層子類甩十。

var playerLayer: AVPlayerLayer {
  return layer as! AVPlayerLayer
}

接下來(lái)船庇,使用gettersetter添加實(shí)際的player定義吭产。

var player: AVPlayer? {
  get {
    return playerLayer.player
  }

  set {
    playerLayer.player = newValue
  }
}

在這里,您只是設(shè)置并獲取您的playerLayerplayer對(duì)象鸭轮。 UIView真的只是中間媒介臣淤。

當(dāng)你開(kāi)始與player本身互動(dòng)時(shí),真正的魔力再次出現(xiàn)窃爷。

構(gòu)建并運(yùn)行以查看...

你已經(jīng)到了一半邑蒋,即使你看不到任何新東西!

2. Writing the Looping Video View - 編寫循環(huán)視頻視圖

接下來(lái)按厘,轉(zhuǎn)到VideoLooperView.swift并準(zhǔn)備好使用VideoPlayerView医吊。 這個(gè)類已經(jīng)有一組VideoClip,正在初始化一個(gè)VideoPlayerView屬性逮京。

您需要做的就是獲取這些片段并想辦法如何在連續(xù)循環(huán)中播放它們卿堂。

首先,添加以下player屬性懒棉。

private let player = AVQueuePlayer()

這里你會(huì)看到這不是普通的AVPlayer實(shí)例草描。 沒(méi)錯(cuò),這是一個(gè)名為AVQueuePlayer的特殊子類策严。 正如您可以通過(guò)名稱猜測(cè)的那樣穗慕,此類允許您提供要播放的項(xiàng)目隊(duì)列。

添加以下方法以開(kāi)始設(shè)置播放器妻导。

private func initializePlayer() {
  videoPlayerView.player = player
}

在這里逛绵,您將player傳遞給videoPlayerView以將其連接到底層AVPlayerLayer

現(xiàn)在是時(shí)候?qū)⒁曨l片段列表添加到player中倔韭,以便它可以開(kāi)始播放暑脆。

添加以下方法來(lái)執(zhí)行此操作。

private func addAllVideosToPlayer() {
  for video in clips {
    //1
    let asset = AVURLAsset(url: video.url)
    let item = AVPlayerItem(asset: asset)

    //2
    player.insert(item, after: player.items().last)
  }
}

在這里狐肢,你循環(huán)遍歷所有clips添吗。 對(duì)于每一個(gè),您:

  • 1) 從每個(gè)視頻clip對(duì)象的URL創(chuàng)建AVURLAsset份名。
  • 2) 然后碟联,使用播放器可用于控制播放的資源創(chuàng)建AVPlayerItem
  • 3) 最后僵腺,使用insert(_after :)方法將每個(gè)項(xiàng)添加到隊(duì)列中鲤孵。

現(xiàn)在,返回initializePlayer()并調(diào)用該方法辰如。

player.volume = 0.0
player.play()

這會(huì)將循環(huán)clip顯示設(shè)置為默認(rèn)自動(dòng)播放和音頻關(guān)閉普监。

最后,您需要調(diào)用您一直在使用的方法。 轉(zhuǎn)到init(clips :)方法并在底部添加此行凯正。

initializePlayer()

構(gòu)建并運(yùn)行以查看完整的節(jié)目毙玻!

不幸的是,當(dāng)最后一個(gè)片段播放完畢后廊散,視頻播放器會(huì)漸變?yōu)楹谏?/p>

3. Doing the Actual Looping - 進(jìn)行實(shí)際循環(huán)

Apple編寫了一個(gè)名為AVPlayerLooper的漂亮新類桑滩。 這個(gè)類將采用單個(gè)播放器項(xiàng)目,并負(fù)責(zé)在循環(huán)中播放該項(xiàng)目所需的所有邏輯允睹。 不幸的是运准,這對(duì)你沒(méi)有幫助!

你想要的是能夠循環(huán)播放所有這些視頻缭受。 看起來(lái)你必須以手動(dòng)方式做事胁澳。 您需要做的就是跟蹤您的播放器和當(dāng)前播放的項(xiàng)目。 當(dāng)它到達(dá)最后一個(gè)視頻時(shí)米者,您將再次將所有剪輯添加到隊(duì)列中听哭。

當(dāng)談到“跟蹤”播放器的信息時(shí),唯一的途徑是使用鍵值觀察KVO塘雳。

是的陆盘,這是蘋果公司提出的更為令人難以置信的API之一。 即便如此败明,如果你小心隘马,它是一種實(shí)時(shí)觀察和響應(yīng)狀態(tài)變化的有效方式。 如果您對(duì)KVO完全不熟悉妻顶,下面就是其簡(jiǎn)要的了解酸员。 基本思想是您在特定屬性的值發(fā)生變化時(shí)注冊(cè)通知。 在這種情況下讳嘱,您想知道player‘s currentItem何時(shí)發(fā)生變化幔嗦。 每次收到通知時(shí),您都會(huì)知道播放器已進(jìn)入下一個(gè)視頻沥潭。

您需要做的第一件事是更改之前定義的player屬性邀泉。 轉(zhuǎn)到文件頂部并將舊定義替換為:

@objc private let player = AVQueuePlayer()

唯一的區(qū)別是你添加了@objc指令。 這告訴Swift你想要將屬性暴露給像KVO這樣的Objective-C之類的東西钝鸽。 要在Swift中使用KVO - 比Objective-C好得多 - 你需要保留對(duì)觀察者的引用汇恤。 在player之后添加以下屬性:

private var token: NSKeyValueObservation?

要開(kāi)始觀察屬性,請(qǐng)返回initializePlayer()并在結(jié)尾處添加以下內(nèi)容:

token = player.observe(\.currentItem) { [weak self] player, _ in
  if player.items().count == 1 {
    self?.addAllVideosToPlayer()
  }
}

在這里拔恰,您每次注冊(cè)playercurrentItem屬性時(shí)都會(huì)注冊(cè)一個(gè)塊因谎。 當(dāng)前視頻更改時(shí),您需要檢查播放器是否已移至最終視頻颜懊。 如果有财岔,那么是時(shí)候?qū)⑺幸曨l剪輯添加回隊(duì)列风皿。

下面,構(gòu)建并運(yùn)行以查看無(wú)限期循環(huán)的clips匠璧。

4. Playing Video Efficiently - 有效播放視頻

在繼續(xù)之前需要注意的一點(diǎn)是桐款,播放視頻是一項(xiàng)資源密集型任務(wù)。 事實(shí)上患朱,即使您開(kāi)始觀看全屏視頻,您的應(yīng)用也會(huì)繼續(xù)播放這些片段炊苫。

要修復(fù)它裁厅,首先將以下兩個(gè)方法添加到VideoLooperView.swift的底部。

func pause() {
  player.pause()
}

func play() {
  player.play()
}

如您所見(jiàn)侨艾,您正在公開(kāi)play()pause()方法执虹,并將消息傳遞給此視圖的播放器。

現(xiàn)在唠梨,轉(zhuǎn)到VideoFeedViewController.swift并找到viewWillDisappear(_ :)袋励。 在那里,添加以下調(diào)用以暫停視頻循環(huán)器当叭。

videoPreviewLooper.pause()

然后茬故,轉(zhuǎn)到viewWillAppear(_ :)并添加匹配的調(diào)用以在用戶返回時(shí)恢復(fù)播放。

videoPreviewLooper.play()

構(gòu)建并運(yùn)行蚁鳖,并轉(zhuǎn)到全屏視頻磺芭。 當(dāng)您返回Feed時(shí),預(yù)覽將從中斷處繼續(xù)醉箕。

5. Playing with Player Controls - 播放器控制

接下來(lái)钾腺,是時(shí)候添加一些控制了。 你的任務(wù)是:

  • 1) 單擊發(fā)生時(shí)取消靜音視頻讥裤。
  • 2) 當(dāng)雙擊發(fā)生時(shí)放棒,在1x和2x速度之間切換。

您將從實(shí)現(xiàn)這些事情所需的實(shí)際方法開(kāi)始己英。 首先间螟,返回VideoLooperView.swift并找到添加播放和暫停方法的位置。

添加以下單擊分頁(yè)處理程序损肛,將在0.01.0之間切換卷寒亥。

@objc func wasTapped() {
  player.volume = player.volume == 1.0 ? 0.0 : 1.0
}

接下來(lái),添加雙擊處理程序荧关。

@objc func wasDoubleTapped() {
  player.rate = player.rate == 1.0 ? 2.0 : 1.0
}

這一點(diǎn)類似于它在1.0和2.0之間切換播放速率溉奕。

接下來(lái),添加以下方法定義忍啤,以創(chuàng)建兩個(gè)手勢(shì)識(shí)別器加勤。

func addGestureRecognizers() {
  // 1
  let tap = UITapGestureRecognizer(target: self, action: #selector(VideoLooperView.wasTapped))
  let doubleTap = UITapGestureRecognizer(target: self,
                                         action: #selector(VideoLooperView.wasDoubleTapped))
  doubleTap.numberOfTapsRequired = 2
  
  // 2
  tap.require(toFail: doubleTap)

  // 3
  addGestureRecognizer(tap)
  addGestureRecognizer(doubleTap)
}

下面一步步的看:

  • 1) 首先仙辟,您創(chuàng)建兩個(gè)手勢(shì)識(shí)別器并告訴他們調(diào)用哪些方法。 你還告訴雙擊它需要兩次點(diǎn)擊鳄梅。
  • 2) 接下來(lái)叠国,您進(jìn)行單擊等待以確保不會(huì)發(fā)生雙擊。 如果您不這樣做戴尸,將始終立即調(diào)用單擊方法粟焊。
  • 3) 然后,將手勢(shì)識(shí)別器添加到視頻視圖中孙蒙。

要完成任務(wù)项棠,請(qǐng)轉(zhuǎn)到init(clip :)并在底部添加以下方法調(diào)用。

addGestureRecognizers()

再次構(gòu)建和運(yùn)行挎峦,您將能夠點(diǎn)擊并雙擊以播放剪輯的速度和音量香追。 這表明添加自定義控制以便與自定義視頻視圖進(jìn)行交互是多么容易。

現(xiàn)在坦胶,您可以將音量調(diào)高了透典!

6. Trying Not to Steal the Show - 不要讓別的因素影響你的展示

最后需要注意的是,如果您打算創(chuàng)建一個(gè)包含視頻的應(yīng)用顿苇,那么考慮一下您的應(yīng)用對(duì)用戶的影響非常重要峭咒。

是的,我知道纪岁,這聽(tīng)起來(lái)非常明顯讹语。 但是你有多少次使用的應(yīng)用程序可以啟動(dòng)靜音視頻但關(guān)閉你的音樂(lè)?

打開(kāi)一些音樂(lè)然后運(yùn)行應(yīng)用程序蜂科。 當(dāng)你這樣做時(shí)顽决,你會(huì)注意到你的音樂(lè)已關(guān)閉,即使視頻循環(huán)沒(méi)有發(fā)出任何噪音导匣!

我的觀點(diǎn)是才菠,您應(yīng)該允許您的用戶關(guān)閉他們自己的音樂(lè),而不是做出如此大膽的假設(shè)贡定。 幸運(yùn)的是赋访,通過(guò)調(diào)整AVAudioSession的設(shè)置來(lái)解決這個(gè)問(wèn)題并不是很難。

轉(zhuǎn)到AppDelegate.swift并將以下導(dǎo)入添加到文件的頂部缓待。

import AVFoundation

接下來(lái)蚓耽,在application(_:didFinishLaunchingWithOptions:)的頂部,添加以下行旋炒。

try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient,
                                                 mode: AVAudioSessionModeMoviePlayback,
                                                 options: [.mixWithOthers])

在這里步悠,您告訴共享AVAudioSession您希望音頻屬于AVAudioSessionCategoryAmbient類別。 默認(rèn)值為AVAudioSessionCategorySoloAmbient瘫镇,它就這樣說(shuō)明了關(guān)閉其他應(yīng)用程序的音頻鼎兽。

您還指定您的應(yīng)用程序正在使用音頻進(jìn)行“電影播放”答姥,并且您可以將聲音與來(lái)自其他來(lái)源的聲音混合使用。

對(duì)于最終構(gòu)建和運(yùn)行谚咬,請(qǐng)重新啟動(dòng)音樂(lè)并再次啟動(dòng)應(yīng)用程序鹦付。

祝大家國(guó)慶節(jié)快樂(lè)!T褙浴敲长!

后記

本篇主要講述了一個(gè)簡(jiǎn)單的視頻流預(yù)覽和播放示例,感興趣的給個(gè)贊或者關(guān)注~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末秉继,一起剝皮案震驚了整個(gè)濱河市祈噪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秕噪,老刑警劉巖钳降,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件厚宰,死亡現(xiàn)場(chǎng)離奇詭異腌巾,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)铲觉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門澈蝙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人撵幽,你說(shuō)我怎么就攤上這事灯荧。” “怎么了盐杂?”我有些...
    開(kāi)封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵逗载,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我链烈,道長(zhǎng)厉斟,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任强衡,我火速辦了婚禮擦秽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘漩勤。我一直安慰自己感挥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布越败。 她就那樣靜靜地躺著触幼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪究飞。 梳的紋絲不亂的頭發(fā)上域蜗,一...
    開(kāi)封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天巨双,我揣著相機(jī)與錄音霉祸,去河邊找鬼筑累。 笑死,一個(gè)胖子當(dāng)著我的面吹牛丝蹭,可吹牛的內(nèi)容都是我干的慢宗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼奔穿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼镜沽!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起贱田,我...
    開(kāi)封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤缅茉,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后男摧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔬墩,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年耗拓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拇颅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乔询,死狀恐怖樟插,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情竿刁,我是刑警寧澤黄锤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站食拜,受9級(jí)特大地震影響鸵熟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜监婶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一旅赢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惑惶,春花似錦煮盼、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至鱼冀,卻和暖如春报破,著一層夾襖步出監(jiān)牢的瞬間悠就,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工充易, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留梗脾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓盹靴,卻偏偏與公主長(zhǎng)得像炸茧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子稿静,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容